diff --git a/docs/devGuide/writingPlugins.md b/docs/devGuide/writingPlugins.md index dab6b367b4..2654abaf53 100644 --- a/docs/devGuide/writingPlugins.md +++ b/docs/devGuide/writingPlugins.md @@ -169,3 +169,12 @@ removing such potential conflicts. Note however, that variable interpolation syntax {% raw %}`{{ variable_name }}`{% endraw %} will act as per normal. Meaning, the user would still be able to use variables in your special tags! + +## Lifecycle hooks + +You may also need to maintain some plugin state during site generation, then reset this when the site or pages are regenerated. + +To do this, you may implement the `beforeSiteGenerate` method. + +- `beforeSiteGenerate()`: Called during initial site generation and subsequent regenerations during live preview. + - No return value is required. diff --git a/packages/core/src/Site/index.js b/packages/core/src/Site/index.js index 459af58588..f61a50b2e3 100644 --- a/packages/core/src/Site/index.js +++ b/packages/core/src/Site/index.js @@ -137,6 +137,7 @@ class Site { this.baseUrlMap = new Set(); this.forceReload = forceReload; this.plugins = {}; + this.pluginsBeforeSiteGenerate = []; /** * @type {undefined | SiteConfig} */ @@ -623,6 +624,7 @@ class Site { .then(() => this.collectBaseUrl()) .then(() => this.collectUserDefinedVariablesMap()) .then(() => this.collectPlugins()) + .then(() => this.collectPluginSiteHooks()) .then(() => this.collectPluginSpecialTags()) .then(() => this.buildAssets()) .then(() => (this.onePagePath ? this.lazyBuildSourceFiles() : this.buildSourceFiles())) @@ -654,6 +656,8 @@ class Site { * Build all pages of the site */ buildSourceFiles() { + this.runBeforeSiteGenerateHooks(); + return new Promise((resolve, reject) => { logger.info('Generating pages...'); this.generatePages() @@ -685,6 +689,8 @@ class Site { * Only build landing page of the site, building more as the author goes to different links. */ lazyBuildSourceFiles() { + this.runBeforeSiteGenerateHooks(); + return new Promise((resolve, reject) => { logger.info('Generating landing page...'); this.generateLandingPage() @@ -708,6 +714,7 @@ class Site { _rebuildAffectedSourceFiles(filePaths) { const filePathArray = Array.isArray(filePaths) ? filePaths : [filePaths]; const uniquePaths = _.uniq(filePathArray); + this.runBeforeSiteGenerateHooks(); return new Promise((resolve, reject) => { this.regenerateAffectedPages(uniquePaths) @@ -727,6 +734,7 @@ class Site { const uniqueUrls = _.uniq(normalizedUrlArray); uniqueUrls.forEach(normalizedUrl => logger.info( `Building ${normalizedUrl} as some of its dependencies were changed since the last visit`)); + this.runBeforeSiteGenerateHooks(); /* Lazy loading only builds the page being viewed, but the user may be quick enough @@ -988,6 +996,15 @@ class Site { })); } + /** + * Collect the before site generate hooks + */ + collectPluginSiteHooks() { + this.pluginsBeforeSiteGenerate = Object.values(this.plugins) + .filter(plugin => plugin.beforeSiteGenerate) + .map(plugin => plugin.beforeSiteGenerate); + } + /** * Collects the special tags of the site's plugins, and injects them into the parsers. */ @@ -1016,6 +1033,13 @@ class Site { }; } + /** + * Executes beforeSiteGenerate hooks from plugins + */ + runBeforeSiteGenerateHooks() { + this.pluginsBeforeSiteGenerate.forEach(cb => cb()); + } + /** * Creates the supplied pages' page generation promises at a throttled rate. * This is done to avoid pushing too many callbacks into the event loop at once. (#1245) diff --git a/packages/core/src/plugins/default/markbind-plugin-plantuml.js b/packages/core/src/plugins/default/markbind-plugin-plantuml.js index 342f2e58a2..aa6985e9c2 100644 --- a/packages/core/src/plugins/default/markbind-plugin-plantuml.js +++ b/packages/core/src/plugins/default/markbind-plugin-plantuml.js @@ -68,9 +68,10 @@ function generateDiagram(imageOutputPath, content) { } module.exports = { - preRender: (content, pluginContext, frontmatter, config) => { + beforeSiteGenerate: () => { processedDiagrams.clear(); - + }, + preRender: (content, pluginContext, frontmatter, config) => { // Processes all tags const $ = cheerio.load(content); $('puml').each((i, tag) => {