From 673cc2e44d6f1694d21ef855aaadc2b73de7e5eb Mon Sep 17 00:00:00 2001 From: SangND Date: Mon, 23 Apr 2018 15:56:28 +0700 Subject: [PATCH 1/4] Add external plugin config --- lib/prepare.js | 24 +++++++++++++++++++++++- lib/util/index.js | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/prepare.js b/lib/prepare.js index 43a0e09c11..0e18edf3b2 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -5,7 +5,7 @@ const yamlParser = require('js-yaml') const yaml = require('yaml-front-matter') const createMarkdown = require('./markdown') const tempPath = path.resolve(__dirname, 'app/.temp') -const { inferTitle, extractHeaders } = require('./util') +const { inferTitle, extractHeaders, loadPlugin, isAsyncFunction } = require('./util') fs.ensureDirSync(tempPath) @@ -62,6 +62,28 @@ if (!Object.assign) Object.assign = require('object-assign')` : `export default function () {}` ) + // 7. handle user plugins + if (options.siteConfig.plugins && Array.isArray(options.siteConfig.plugins)) { + const { plugins } = options.siteConfig + for (const plugin of plugins) { + let pluginRequired + if (typeof plugin === 'string') { + pluginRequired = loadPlugin(plugin, options) + } + if (typeof plugin === 'object') { + pluginRequired = loadPlugin(plugin.resolve, options) + if (plugin.options) { + pluginRequired = pluginRequired(plugin.options) + } + } + if (isAsyncFunction(pluginRequired)) { + await pluginRequired(options) + } else { + pluginRequired(options) + } + } + } + return options } diff --git a/lib/util/index.js b/lib/util/index.js index bfa48e24cf..557eac68da 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -71,3 +71,25 @@ exports.extractHeaders = (content, include = [], md) => { cache.set(key, res) return res } + +exports.loadPlugin = (pluginPath, options) => { + const fs = require('fs-extra') + const path = require('path') + const vuepressDir = path.resolve(options.sourceDir, '.vuepress') + let plugin + try { + if (fs.existsSync(path.resolve(vuepressDir, pluginPath))) { + plugin = require(path.resolve(vuepressDir, pluginPath)) + } else { + plugin = require(pluginPath) + } + } catch (e) { + throw e + } + return plugin +} + +exports.isAsyncFunction = (func) => { + const AsyncFunction = (async () => {}).constructor + return (func instanceof AsyncFunction && AsyncFunction !== Function) +} From 5cdb74447e293dad9867d3dbf56976ac25b683af Mon Sep 17 00:00:00 2001 From: SangND Date: Tue, 24 Apr 2018 18:02:14 +0700 Subject: [PATCH 2/4] Support Plugin return Promise --- lib/prepare.js | 12 +++++++----- lib/util/index.js | 5 ----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/prepare.js b/lib/prepare.js index c16f46ba76..5559131475 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -5,7 +5,7 @@ const yamlParser = require('js-yaml') const tomlParser = require('toml') const createMarkdown = require('./markdown') const tempPath = path.resolve(__dirname, 'app/.temp') -const { inferTitle, extractHeaders, parseFrontmatter, loadPlugin, isAsyncFunction } = require('./util') +const { inferTitle, extractHeaders, parseFrontmatter, loadPlugin } = require('./util') fs.ensureDirSync(tempPath) @@ -88,10 +88,12 @@ if (!Object.assign) Object.assign = require('object-assign')` pluginRequired = pluginRequired(plugin.options) } } - if (isAsyncFunction(pluginRequired)) { - await pluginRequired(options) - } else { - pluginRequired(options) + if (pluginRequired) { + try { + await pluginRequired(options) + } catch (e) { + throw e + } } } } diff --git a/lib/util/index.js b/lib/util/index.js index 7ff530d802..2b080948af 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -101,8 +101,3 @@ exports.loadPlugin = (pluginPath, options) => { } return plugin } - -exports.isAsyncFunction = (func) => { - const AsyncFunction = (async () => {}).constructor - return (func instanceof AsyncFunction && AsyncFunction !== Function) -} From 8aec2146f50f5b577c2ae975046fff82eb859110 Mon Sep 17 00:00:00 2001 From: SangND Date: Tue, 24 Apr 2018 20:58:11 +0700 Subject: [PATCH 3/4] Change plugin API to first-order function, use Babel Style for configure extra options --- lib/prepare.js | 18 +++++++++--------- lib/util/index.js | 27 +++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/prepare.js b/lib/prepare.js index 5559131475..160ef3cd60 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -5,7 +5,7 @@ const yamlParser = require('js-yaml') const tomlParser = require('toml') const createMarkdown = require('./markdown') const tempPath = path.resolve(__dirname, 'app/.temp') -const { inferTitle, extractHeaders, parseFrontmatter, loadPlugin } = require('./util') +const { inferTitle, extractHeaders, parseFrontmatter, loadPlugin, cloneOptions } = require('./util') fs.ensureDirSync(tempPath) @@ -77,20 +77,20 @@ if (!Object.assign) Object.assign = require('object-assign')` // 7. handle user plugins if (options.siteConfig.plugins && Array.isArray(options.siteConfig.plugins)) { const { plugins } = options.siteConfig + for (const plugin of plugins) { let pluginRequired + let pluginOptions + const vuepressOptions = cloneOptions(options) if (typeof plugin === 'string') { - pluginRequired = loadPlugin(plugin, options) - } - if (typeof plugin === 'object') { - pluginRequired = loadPlugin(plugin.resolve, options) - if (plugin.options) { - pluginRequired = pluginRequired(plugin.options) - } + pluginRequired = loadPlugin(plugin, sourceDir) + } else if (Array.isArray(plugin)) { + pluginRequired = loadPlugin(plugin[0], sourceDir) + pluginOptions = plugin[1] } if (pluginRequired) { try { - await pluginRequired(options) + await pluginRequired({ vuepressOptions, pluginOptions }) } catch (e) { throw e } diff --git a/lib/util/index.js b/lib/util/index.js index 2b080948af..f5179a96f9 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -85,10 +85,10 @@ exports.extractHeaders = (content, include = [], md) => { return res } -exports.loadPlugin = (pluginPath, options) => { +exports.loadPlugin = (pluginPath, sourceDir) => { const fs = require('fs-extra') const path = require('path') - const vuepressDir = path.resolve(options.sourceDir, '.vuepress') + const vuepressDir = path.resolve(sourceDir, '.vuepress') let plugin try { if (fs.existsSync(path.resolve(vuepressDir, pluginPath))) { @@ -101,3 +101,26 @@ exports.loadPlugin = (pluginPath, options) => { } return plugin } + +exports.cloneOptions = (options) => { + const optionClone = {} + const readonlyProperties = ['sourceDir', 'outDir', 'publicPath', 'markdown', 'themePath', 'useDefaultTheme', 'notFoundPath'] + const writableProperties = ['siteConfig', 'pageFiles', 'siteData'] + + readonlyProperties.forEach(prop => { + Object.defineProperty(optionClone, prop, { + value: options[prop], + enumerable: true + }) + }) + + writableProperties.forEach(prop => { + Object.defineProperty(optionClone, prop, { + value: options[prop], + writable: true, + enumerable: true + }) + }) + + return optionClone +} From 9b49d9486a3cccad2c677262cc4ebb8a80e671f7 Mon Sep 17 00:00:00 2001 From: SangND Date: Tue, 24 Apr 2018 21:01:09 +0700 Subject: [PATCH 4/4] Rename vuepressOptions to exposeOptions --- lib/prepare.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/prepare.js b/lib/prepare.js index 160ef3cd60..d32a6bde08 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -81,7 +81,7 @@ if (!Object.assign) Object.assign = require('object-assign')` for (const plugin of plugins) { let pluginRequired let pluginOptions - const vuepressOptions = cloneOptions(options) + const exposedOptions = cloneOptions(options) if (typeof plugin === 'string') { pluginRequired = loadPlugin(plugin, sourceDir) } else if (Array.isArray(plugin)) { @@ -90,7 +90,7 @@ if (!Object.assign) Object.assign = require('object-assign')` } if (pluginRequired) { try { - await pluginRequired({ vuepressOptions, pluginOptions }) + await pluginRequired({ exposedOptions, pluginOptions }) } catch (e) { throw e }