Skip to content
2 changes: 2 additions & 0 deletions docs/userGuide/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
**_Live preview_** is:
- Regeneration of affected content upon any change to <tooltip content="`.md`, `.mbd`, `.mbdf`, `.njk` files ... anything your content depends on!">source files</tooltip>, then reloading the updated site in the Browser.

- Regeneration will also occur upon any modification to attributes in `site.json` with the exception of [`baseUrl`](siteJsonFile.md#baseurl).

- Copying <tooltip content="files that don't affect page generation (eg. images), but are used in the site">assets</tooltip> to the site output folder.

Use [the `serve` command](cliCommands.html#serve-command) to launch a live preview.
Expand Down
4 changes: 4 additions & 0 deletions docs/userGuide/siteJsonFile.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ Here is a typical `site.json` file:

<include src="deployingTheSite.md#warning-about-baseUrl" />

<box type="warning">

Note: `baseUrl` does not support [live preview](glossary.md#live-preview) as there is no use case for changing it in during `markbind serve`.
</box>

#### **`faviconPath`**

Expand Down
78 changes: 71 additions & 7 deletions packages/core/src/Site/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,13 @@ class Site {
this.baseUrlMap = new Set(candidates.map(candidate => path.dirname(candidate)));
this.variableProcessor = new VariableProcessor(this.rootPath, this.baseUrlMap);

this.buildManagers();
}

/**
* Set up the managers used with the configurations.
*/
buildManagers() {
const config = {
baseUrlMap: this.baseUrlMap,
baseUrl: this.siteConfig.baseUrl,
Expand Down Expand Up @@ -633,7 +640,7 @@ class Site {
await this.buildAssets();
await (this.onePagePath ? this.lazyBuildSourceFiles() : this.buildSourceFiles());
await this.copyCoreWebAsset();
await this.copyBootswatchTheme();
await this.copyBootstrapTheme(false);
await this.copyFontAwesomeAsset();
await this.copyOcticonsAsset();
await this.writeSiteData();
Expand Down Expand Up @@ -773,7 +780,7 @@ class Site {
}

async _rebuildSourceFiles() {
logger.info('Page added or removed, updating list of site\'s pages...');
logger.info('Pages or site config modified, updating pages...');
this.beforeSiteGenerate();

this.layoutManager.removeLayouts();
Expand Down Expand Up @@ -844,9 +851,19 @@ class Site {
}

async reloadSiteConfig() {
const oldSiteConfig = this.siteConfig;
const oldAddressablePages = this.addressablePages.slice();
const oldPagesSrc = oldAddressablePages.map(page => page.src);
await this.readSiteConfig();
await this.handleIgnoreReload(oldSiteConfig.ignore);
await this.handlePageReload(oldAddressablePages, oldPagesSrc, oldSiteConfig);
await this.handleStyleReload(oldSiteConfig.style);
}

/**
* Handles the rebuilding of modified pages
*/
async handlePageReload(oldAddressablePages, oldPagesSrc, oldSiteConfig) {
this.collectAddressablePages();

// Comparator for the _differenceWith comparison below
Expand All @@ -856,8 +873,24 @@ class Site {
const removedPages = _.differenceWith(oldAddressablePages, this.addressablePages, isNewPage)
.map(filePath => Site.setExtension(filePath.src, '.html'));

if (!_.isEmpty(addedPages) || !_.isEmpty(removedPages)) {
// Checks if any attributes of site.json requiring a global rebuild are modified
const isGlobalConfigModified = () => !_.isEqual(oldSiteConfig.faviconPath, this.siteConfig.faviconPath)
|| !_.isEqual(oldSiteConfig.titlePrefix, this.siteConfig.titlePrefix)
|| !_.isEqual(oldSiteConfig.style, this.siteConfig.style)
|| !_.isEqual(oldSiteConfig.externalScripts, this.siteConfig.externalScripts)
|| !_.isEqual(oldSiteConfig.globalOverride, this.siteConfig.globalOverride)
|| !_.isEqual(oldSiteConfig.plugins, this.siteConfig.plugins)
|| !_.isEqual(oldSiteConfig.pluginsContext, this.siteConfig.pluginsContext)
|| !_.isEqual(oldSiteConfig.headingIndexingLevel, this.siteConfig.headingIndexingLevel)
|| !_.isEqual(oldSiteConfig.enableSearch, this.siteConfig.enableSearch)
|| !_.isEqual(oldSiteConfig.disableHtmlBeautify, this.siteConfig.disableHtmlBeautify)
|| !_.isEqual(oldSiteConfig.timeZone, this.siteConfig.timeZone)
|| !_.isEqual(oldSiteConfig.locale, this.siteConfig.locale)
|| !_.isEqual(oldSiteConfig.intrasiteLinkValidation, this.siteConfig.intrasiteLinkValidation);

if (isGlobalConfigModified() || !_.isEmpty(addedPages) || !_.isEmpty(removedPages)) {
await this.removeAsset(removedPages);
this.buildManagers();
await this._rebuildSourceFiles();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional remark (no action needed):

EDIT: After looking around at the other handlers (addHandler and removeHandler), it seems all pages should be rebuilt if the added/removed file is a page/dependency of page.

This has been existing behaviour for a long while already but can probably be made into an issue 🙂

Per #1514's comment, the number of dependent pages generated / regenerated can be improved later as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I'll open an issue for this and the previous discussion.

await this.writeSiteData();
} else {
Expand Down Expand Up @@ -889,6 +922,29 @@ class Site {
});
}

/**
* Handles the reloading of ignore attributes
*/
async handleIgnoreReload(oldIgnore) {
const assetsToRemove = _.difference(this.siteConfig.ignore, oldIgnore);
Comment thread
jonahtanjz marked this conversation as resolved.

if (!_.isEqual(oldIgnore, this.siteConfig.ignore)) {
Comment thread
jonahtanjz marked this conversation as resolved.
await this._removeMultipleAssets(assetsToRemove);
this.buildManagers();
await this.buildAssets();
}
}

/**
* Handles the reloading of the style attribute if it has been modified
*/
async handleStyleReload(oldStyle) {
if (!_.isEqual(oldStyle.bootstrapTheme, this.siteConfig.style.bootstrapTheme)) {
await this.copyBootstrapTheme(true);
logger.info('Updated bootstrap theme');
}
}

/**
* Checks if a specified file path is a dependency of a page
* @param {string} filePath file path to check
Expand Down Expand Up @@ -1223,15 +1279,23 @@ class Site {
}

/**
* Copies bootswatch theme to the assets folder if a valid theme is specified
* Copies bootstrap theme to the assets folder if a valid theme is specified
* @param {Boolean} isRebuild only true if it is a rebuild
*/
copyBootswatchTheme() {
copyBootstrapTheme(isRebuild) {
const { theme } = this.siteConfig;
if (!theme || !_.has(SUPPORTED_THEMES_PATHS, theme)) {

/**
* If it is the initial build using the default theme or if the theme specified
* is not valid, then do nothing.
*/
if ((!isRebuild && !theme) || (theme && !_.has(SUPPORTED_THEMES_PATHS, theme))) {
return _.noop;
}

const themeSrcPath = SUPPORTED_THEMES_PATHS[theme];
const themeSrcPath = !theme
? require.resolve('@markbind/core-web/asset/css/bootstrap.min.css')
: SUPPORTED_THEMES_PATHS[theme];
const themeDestPath = path.join(this.siteAssetsDestPath, 'css', 'bootstrap.min.css');

return fs.copy(themeSrcPath, themeDestPath);
Expand Down