diff --git a/packages/cli/index.js b/packages/cli/index.js index aac678a853..2145f5a19e 100755 --- a/packages/cli/index.js +++ b/packages/cli/index.js @@ -18,6 +18,7 @@ const { INDEX_MARKDOWN_FILE, INDEX_MARKBIND_FILE, LAZY_LOADING_SITE_FILE_NAME, + SITE_CONFIG_NAME, } = require('@markbind/core/src/Site/constants'); const cliUtil = require('./src/util/cliUtil'); @@ -152,6 +153,9 @@ program const changeHandler = (filePath) => { logger.info(`[${new Date().toLocaleTimeString()}] Reload for file change: ${filePath}`); Promise.resolve('').then(() => { + if (path.basename(filePath) === SITE_CONFIG_NAME) { + return site.reloadSiteConfig(); + } if (site.isDependencyOfPage(filePath)) { return site.rebuildAffectedSourceFiles(filePath); } diff --git a/packages/core/src/Site/index.js b/packages/core/src/Site/index.js index 19e6c06942..27647e5282 100644 --- a/packages/core/src/Site/index.js +++ b/packages/core/src/Site/index.js @@ -31,9 +31,12 @@ const { const _ = {}; _.difference = require('lodash/difference'); +_.differenceWith = require('lodash/differenceWith'); _.flatMap = require('lodash/flatMap'); _.has = require('lodash/has'); _.isBoolean = require('lodash/isBoolean'); +_.isEmpty = require('lodash/isEmpty'); +_.isEqual = require('lodash/isEqual'); _.isUndefined = require('lodash/isUndefined'); _.noop = require('lodash/noop'); _.omitBy = require('lodash/omitBy'); @@ -816,6 +819,52 @@ class Site { } } + async reloadSiteConfig() { + const oldAddressablePages = this.addressablePages.slice(); + const oldPagesSrc = oldAddressablePages.map(page => page.src); + await this.readSiteConfig(); + this.collectAddressablePages(); + + // Comparator for the _differenceWith comparison below + const isNewPage = (newPage, oldPage) => _.isEqual(newPage, oldPage) || newPage.src === oldPage.src; + + const addedPages = _.differenceWith(this.addressablePages, oldAddressablePages, isNewPage); + const removedPages = _.differenceWith(oldAddressablePages, this.addressablePages, isNewPage) + .map(filePath => Site.setExtension(filePath.src, '.html')); + + if (!_.isEmpty(addedPages) || !_.isEmpty(removedPages)) { + await this.removeAsset(removedPages); + await this._rebuildSourceFiles(); + await this.writeSiteData(); + } else { + // Get pages with edited attributes but with the same src + const editedPages = _.differenceWith(this.addressablePages, oldAddressablePages, (newPage, oldPage) => { + if (!_.isEqual(newPage, oldPage)) { + return !oldPagesSrc.includes(newPage.src); + } + return true; + }); + this.updatePages(editedPages); + const siteConfigDirectory = path.dirname(path.join(this.rootPath, this.siteConfigPath)); + this.regenerateAffectedPages(editedPages.map(page => path.join(siteConfigDirectory, page.src))); + } + } + + /** + * Creates new pages and replaces the original pages with the updated version + */ + updatePages(pagesToUpdate) { + pagesToUpdate.forEach((pageToUpdate) => { + this.pages.forEach((page, index) => { + if (page.pageConfig.src === pageToUpdate.src) { + const newPage = this.createNewPage(pageToUpdate, this.getFavIconUrl()); + newPage.resetState(); + this.pages[index] = newPage; + } + }); + }); + } + /** * Checks if a specified file path is a dependency of a page * @param {string} filePath file path to check @@ -866,7 +915,16 @@ class Site { * @param {String} faviconUrl */ mapAddressablePagesToPages(addressablePages, faviconUrl) { - this.pages = addressablePages.map(page => this.createPage({ + this.pages = addressablePages.map(page => this.createNewPage(page, faviconUrl)); + } + + /** + * Creates and returns a new Page with the given page config details and favicon url + * @param {Page} page config + * @param {String} faviconUrl of the page + */ + createNewPage(page, faviconUrl) { + return this.createPage({ faviconUrl, pageSrc: page.src, title: page.title, @@ -874,7 +932,7 @@ class Site { frontmatter: page.frontmatter, searchable: page.searchable !== 'no', externalScripts: page.externalScripts, - })); + }); } /**