From 46e1992f8f89f54f9c372179d6bf0fa9c464475a Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sat, 2 Jun 2018 02:04:54 +0800 Subject: [PATCH 001/242] feat: init plugin --- docs/.vuepress/config.js | 5 ++ lib/plugin-api/hook.js | 28 ++++++ lib/plugin-api/index.js | 89 +++++++++++++++++++ lib/plugin-api/util.js | 34 +++++++ .../vuepress-plugin-last-updated/index.js | 15 ++++ lib/prepare/resolveOptions.js | 23 ++++- 6 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 lib/plugin-api/hook.js create mode 100644 lib/plugin-api/index.js create mode 100644 lib/plugin-api/util.js create mode 100644 lib/plugins/vuepress-plugin-last-updated/index.js diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index ad70d04dba..a8522e1147 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -25,6 +25,11 @@ module.exports = { ], serviceWorker: true, theme: 'vue', + plugins: [ + [ + require('../../lib/plugins/vuepress-plugin-last-updated/index'), + ] + ], themeConfig: { repo: 'vuejs/vuepress', editLinks: true, diff --git a/lib/plugin-api/hook.js b/lib/plugin-api/hook.js new file mode 100644 index 0000000000..0c7108ffcd --- /dev/null +++ b/lib/plugin-api/hook.js @@ -0,0 +1,28 @@ +module.exports = class Hook { + constructor (name) { + this.name = name + this.handlers = [] + } + + tap (symbol, handler) { + if (typeof handler !== 'function') { + return + } + this.handlers.push({ symbol, handler }) + return this + } + + remove (symbol) { + const index = this.handlers.findIndex(item => item.symbol === symbol) + if (index !== -1) { + this.handlers.splice(index, 1) + } + return this + } + + async run () { + for (const item of this.handlers) { + await item.handler.apply(null, arguments) + } + } +} diff --git a/lib/plugin-api/index.js b/lib/plugin-api/index.js new file mode 100644 index 0000000000..f33f30f7b2 --- /dev/null +++ b/lib/plugin-api/index.js @@ -0,0 +1,89 @@ +const { resolvePlugin, inferPluginName } = require('./util') +const Hook = require('./hook') + +module.exports = class Plugin { + constructor (pluginConfigs) { + this.hooks = {} + this.apis = {} + this.extendHooks([ + 'ready', + 'compiled', + 'updated', + 'generated' + ]) + this.extendAPIs([ + 'client', + 'chainWebpack', + 'enhanceDevServer', + 'extendMarkdown', + 'enhanceAppFiles', + 'outFiles', + 'extendPageData' + ]) + this.resolvePluginConfig(pluginConfigs) + } + + extendHooks (hooks) { + hooks.forEach(hook => { + this.hooks[hook] = new Hook(hook) + }) + } + + extendAPIs (apis) { + apis.forEach(api => { + this.apis[api] = [] + }) + } + + resolvePluginConfigs (pluginConfigs) { + pluginConfigs.forEach(([name, pluginOptions]) => { + let plugin = resolvePlugin(name) + if (typeof plugin === 'function') { + plugin = plugin(pluginOptions) + } + plugin = Object.assign(plugin, { name: inferPluginName(name, plugin) }) + this.resolvePluginConfig(plugin) + }) + } + + registerHook (name, hook, symbol) { + this.hooks[name].tap(symbol, hook) + return this + } + + registerAPI (name, api) { + this.apis[name].push(api) + return this + } + + resolvePluginConfig ({ + name, + client, + chainWebpack, + enhanceDevServer, + extendMarkdown, + enhanceAppFiles, + outFiles, + extendPageData, + ready, + compiled, + updated, + generated + }) { + console.log(this.hooks) + this + .registerHook('ready', ready, name) + .registerHook('compiled', compiled, name) + .registerHook('updated', updated, name) + .registerHook('generated', generated, name) + + this + .registerAPI('client', client) + .registerAPI('chainWebpack', chainWebpack) + .registerAPI('enhanceDevServer', enhanceDevServer) + .registerAPI('extendMarkdown', extendMarkdown) + .registerAPI('enhanceAppFiles', enhanceAppFiles) + .registerAPI('outFiles', outFiles) + .registerAPI('extendPageData', extendPageData) + } +} diff --git a/lib/plugin-api/util.js b/lib/plugin-api/util.js new file mode 100644 index 0000000000..9fe67c9c34 --- /dev/null +++ b/lib/plugin-api/util.js @@ -0,0 +1,34 @@ +const logger = require('../util/logger') +const chalk = require('chalk') + +exports.resolvePlugin = function (pluginName) { + if (typeof pluginName === 'function' || typeof pluginName === 'object') { + return pluginName + } + if (typeof pluginName === 'string') { + try { + return require(pluginName.startsWith('vuepress-plugin-') + ? pluginName + : `vuepress-plugin-${pluginName}` + ) + } catch (err) { + console.error(chalk.red(logger.error(`\n[vuepress] Cannot resolve plugin: ${pluginName}\n`, false))) + throw new Error(err) + } + } + logger.warn(`\n[vuepress] Invalid plugin usage: ${chalk.yellow(pluginName)}\n`) +} + +exports.inferPluginName = function (pluginName, pluginConfig) { + if (pluginConfig.name) { + return pluginConfig.name + } + if (typeof pluginName === 'string') { + if (pluginName.startsWith('vuepress-plugin-')) { + return pluginName.slice(16) + } + return pluginName + } + // ensure each plugin have a unique name. + return Date.now().toString(16) +} diff --git a/lib/plugins/vuepress-plugin-last-updated/index.js b/lib/plugins/vuepress-plugin-last-updated/index.js new file mode 100644 index 0000000000..6a27a26d17 --- /dev/null +++ b/lib/plugins/vuepress-plugin-last-updated/index.js @@ -0,0 +1,15 @@ +const path = require('path') +const spawn = require('cross-spawn') + +module.exports = options => ({ + client: path.resolve(__dirname, 'client.js'), + extendPageData (filepath) { + return { + lastModified: getGitLastUpdatedTimeStamp(filepath) + } + } +}) + +function getGitLastUpdatedTimeStamp (filepath) { + return parseInt(spawn.sync('git', ['log', '-1', '--format=%ct', filepath]).stdout.toString('utf-8')) * 1000 +} diff --git a/lib/prepare/resolveOptions.js b/lib/prepare/resolveOptions.js index 76fa2fcc78..5a1323ce17 100644 --- a/lib/prepare/resolveOptions.js +++ b/lib/prepare/resolveOptions.js @@ -2,6 +2,7 @@ const fs = require('fs-extra') const path = require('path') const globby = require('globby') const createMarkdown = require('../markdown') +const Plugin = require('../plugin-api') const loadConfig = require('./loadConfig') const { encodePath, fileToPath, sort, getGitLastUpdatedTimeStamp } = require('./util') const { @@ -32,6 +33,14 @@ module.exports = async function resolveOptions (sourceDir) { }) } + // resolve plugins + const plugins = (Array.isArray(siteConfig.plugins) + ? siteConfig.plugins + : [] + ) + const plugin = new Plugin(plugins) + console.log(plugin) + // resolve outDir const outDir = siteConfig.dest ? path.resolve(siteConfig.dest) @@ -99,7 +108,7 @@ module.exports = async function resolveOptions (sourceDir) { const isAlgoliaSearch = ( themeConfig.algolia || Object.keys(siteConfig.locales && themeConfig.locales || {}) - .some(base => themeConfig.locales[base].algolia) + .some(base => themeConfig.locales[base].algolia) ) // resolve markdown @@ -112,7 +121,7 @@ module.exports = async function resolveOptions (sourceDir) { const shouldResolveLastUpdated = ( themeConfig.lastUpdated || Object.keys(siteConfig.locales && themeConfig.locales || {}) - .some(base => themeConfig.locales[base].lastUpdated) + .some(base => themeConfig.locales[base].lastUpdated) ) // resolve pagesData @@ -124,6 +133,13 @@ module.exports = async function resolveOptions (sourceDir) { path: encodePath(fileToPath(file)) } + for (const fn of plugin.apis.extendPageData) { + const res = await fn(file) + if (typeof res === 'object') { + Object.assign(data, res) + } + } + if (shouldResolveLastUpdated) { data.lastUpdated = getGitLastUpdatedTimeStamp(filepath) } @@ -178,7 +194,8 @@ module.exports = async function resolveOptions (sourceDir) { themeEnhanceAppPath, useDefaultTheme, isAlgoliaSearch, - markdown + markdown, + plugin } return options From 50e346730b8d3a4181a34dfe6258e5251a1ae65c Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sat, 2 Jun 2018 02:31:22 +0800 Subject: [PATCH 002/242] feat: make lastUpdated as a plugin. --- docs/.vuepress/config.js | 2 +- lib/plugin-api/index.js | 27 +++++++++++-------- .../vuepress-plugin-last-updated/index.js | 4 +-- lib/prepare/resolveOptions.js | 21 ++++----------- lib/prepare/util.js | 5 ---- 5 files changed, 24 insertions(+), 35 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index a8522e1147..46e4469e88 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -27,7 +27,7 @@ module.exports = { theme: 'vue', plugins: [ [ - require('../../lib/plugins/vuepress-plugin-last-updated/index'), + require('../../lib/plugins/vuepress-plugin-last-updated/index') ] ], themeConfig: { diff --git a/lib/plugin-api/index.js b/lib/plugin-api/index.js index f33f30f7b2..e7072d02c0 100644 --- a/lib/plugin-api/index.js +++ b/lib/plugin-api/index.js @@ -20,7 +20,7 @@ module.exports = class Plugin { 'outFiles', 'extendPageData' ]) - this.resolvePluginConfig(pluginConfigs) + this.resolvePluginConfigs(pluginConfigs) } extendHooks (hooks) { @@ -35,27 +35,32 @@ module.exports = class Plugin { }) } + registerHook (name, hook, symbol) { + if (hook) { + this.hooks[name].tap(symbol, hook) + } + return this + } + + registerAPI (name, api) { + if (api) { + this.apis[name].push(api) + } + return this + } + resolvePluginConfigs (pluginConfigs) { pluginConfigs.forEach(([name, pluginOptions]) => { let plugin = resolvePlugin(name) if (typeof plugin === 'function') { plugin = plugin(pluginOptions) } + console.log(plugin) plugin = Object.assign(plugin, { name: inferPluginName(name, plugin) }) this.resolvePluginConfig(plugin) }) } - registerHook (name, hook, symbol) { - this.hooks[name].tap(symbol, hook) - return this - } - - registerAPI (name, api) { - this.apis[name].push(api) - return this - } - resolvePluginConfig ({ name, client, diff --git a/lib/plugins/vuepress-plugin-last-updated/index.js b/lib/plugins/vuepress-plugin-last-updated/index.js index 6a27a26d17..0945cd0d41 100644 --- a/lib/plugins/vuepress-plugin-last-updated/index.js +++ b/lib/plugins/vuepress-plugin-last-updated/index.js @@ -3,9 +3,9 @@ const spawn = require('cross-spawn') module.exports = options => ({ client: path.resolve(__dirname, 'client.js'), - extendPageData (filepath) { + extendPageData ({ filepath }) { return { - lastModified: getGitLastUpdatedTimeStamp(filepath) + lastUpdated: getGitLastUpdatedTimeStamp(filepath) } } }) diff --git a/lib/prepare/resolveOptions.js b/lib/prepare/resolveOptions.js index 5a1323ce17..5b9f9e576b 100644 --- a/lib/prepare/resolveOptions.js +++ b/lib/prepare/resolveOptions.js @@ -4,7 +4,7 @@ const globby = require('globby') const createMarkdown = require('../markdown') const Plugin = require('../plugin-api') const loadConfig = require('./loadConfig') -const { encodePath, fileToPath, sort, getGitLastUpdatedTimeStamp } = require('./util') +const { encodePath, fileToPath, sort } = require('./util') const { inferTitle, extractHeaders, @@ -117,33 +117,22 @@ module.exports = async function resolveOptions (sourceDir) { // resolve pageFiles const pageFiles = sort(await globby(['**/*.md', '!.vuepress', '!node_modules'], { cwd: sourceDir })) - // resolve lastUpdated - const shouldResolveLastUpdated = ( - themeConfig.lastUpdated || - Object.keys(siteConfig.locales && themeConfig.locales || {}) - .some(base => themeConfig.locales[base].lastUpdated) - ) - // resolve pagesData - const pagesData = await Promise.all(pageFiles.map(async (file) => { - const filepath = path.resolve(sourceDir, file) + const pagesData = await Promise.all(pageFiles.map(async (relative) => { + const filepath = path.resolve(sourceDir, relative) const key = 'v-' + Math.random().toString(16).slice(2) const data = { key, - path: encodePath(fileToPath(file)) + path: encodePath(fileToPath(relative)) } for (const fn of plugin.apis.extendPageData) { - const res = await fn(file) + const res = await fn({ filepath, relative, key, sourceDir }) if (typeof res === 'object') { Object.assign(data, res) } } - if (shouldResolveLastUpdated) { - data.lastUpdated = getGitLastUpdatedTimeStamp(filepath) - } - // extract yaml frontmatter const content = await fs.readFile(filepath, 'utf-8') const frontmatter = parseFrontmatter(content) diff --git a/lib/prepare/util.js b/lib/prepare/util.js index efa96cc9b7..66e7be2aa1 100644 --- a/lib/prepare/util.js +++ b/lib/prepare/util.js @@ -1,5 +1,4 @@ const path = require('path') -const spawn = require('cross-spawn') const fs = require('fs-extra') const globby = require('globby') @@ -74,7 +73,3 @@ exports.sort = function (arr) { exports.encodePath = function (userpath) { return userpath.split('/').map(item => encodeURIComponent(item)).join('/') } - -exports.getGitLastUpdatedTimeStamp = function (filepath) { - return parseInt(spawn.sync('git', ['log', '-1', '--format=%ct', filepath]).stdout.toString('utf-8')) * 1000 -} From 1a9689c1e789bbd2c2d67f6a3b774572561fa755 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sat, 2 Jun 2018 02:49:02 +0800 Subject: [PATCH 003/242] feat: support Array | Array> --- docs/.vuepress/config.js | 4 +--- lib/plugin-api/index.js | 10 ++++++---- lib/prepare/resolveOptions.js | 1 - .../vuepress-plugin-last-updated/index.js | 0 4 files changed, 7 insertions(+), 8 deletions(-) rename {lib/plugins => packages}/vuepress-plugin-last-updated/index.js (100%) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 46e4469e88..46bbeaa6dd 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -26,9 +26,7 @@ module.exports = { serviceWorker: true, theme: 'vue', plugins: [ - [ - require('../../lib/plugins/vuepress-plugin-last-updated/index') - ] + require('../../packages/vuepress-plugin-last-updated/index') ], themeConfig: { repo: 'vuejs/vuepress', diff --git a/lib/plugin-api/index.js b/lib/plugin-api/index.js index e7072d02c0..b181753751 100644 --- a/lib/plugin-api/index.js +++ b/lib/plugin-api/index.js @@ -1,7 +1,7 @@ const { resolvePlugin, inferPluginName } = require('./util') const Hook = require('./hook') -module.exports = class Plugin { +module.exports = class VuePressPlugin { constructor (pluginConfigs) { this.hooks = {} this.apis = {} @@ -50,12 +50,15 @@ module.exports = class Plugin { } resolvePluginConfigs (pluginConfigs) { - pluginConfigs.forEach(([name, pluginOptions]) => { + pluginConfigs.forEach(pluginConfigs => { + pluginConfigs = Array.isArray(pluginConfigs) + ? pluginConfigs + : [pluginConfigs] + const [name, pluginOptions] = pluginConfigs let plugin = resolvePlugin(name) if (typeof plugin === 'function') { plugin = plugin(pluginOptions) } - console.log(plugin) plugin = Object.assign(plugin, { name: inferPluginName(name, plugin) }) this.resolvePluginConfig(plugin) }) @@ -75,7 +78,6 @@ module.exports = class Plugin { updated, generated }) { - console.log(this.hooks) this .registerHook('ready', ready, name) .registerHook('compiled', compiled, name) diff --git a/lib/prepare/resolveOptions.js b/lib/prepare/resolveOptions.js index 5b9f9e576b..3001ba8ef3 100644 --- a/lib/prepare/resolveOptions.js +++ b/lib/prepare/resolveOptions.js @@ -39,7 +39,6 @@ module.exports = async function resolveOptions (sourceDir) { : [] ) const plugin = new Plugin(plugins) - console.log(plugin) // resolve outDir const outDir = siteConfig.dest diff --git a/lib/plugins/vuepress-plugin-last-updated/index.js b/packages/vuepress-plugin-last-updated/index.js similarity index 100% rename from lib/plugins/vuepress-plugin-last-updated/index.js rename to packages/vuepress-plugin-last-updated/index.js From ea5f04b1b69e53e5731a87e56ccc43564aeab3c2 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Sat, 2 Jun 2018 17:53:34 +0800 Subject: [PATCH 004/242] feat: add types check and friendly warn log for plugin options --- lib/plugin-api/index.js | 54 ++++++++----- lib/plugin-api/util.js | 75 +++++++++++++++---- .../vuepress-plugin-last-updated/index.js | 1 + 3 files changed, 96 insertions(+), 34 deletions(-) diff --git a/lib/plugin-api/index.js b/lib/plugin-api/index.js index b181753751..d8cdf13df7 100644 --- a/lib/plugin-api/index.js +++ b/lib/plugin-api/index.js @@ -1,5 +1,7 @@ -const { resolvePlugin, inferPluginName } = require('./util') +const chalk = require('chalk') +const { resolvePlugin, inferPluginName, assertTypes } = require('./util') const Hook = require('./hook') +const logger = require('../util/logger') module.exports = class VuePressPlugin { constructor (pluginConfigs) { @@ -35,16 +37,28 @@ module.exports = class VuePressPlugin { }) } - registerHook (name, hook, symbol) { - if (hook) { - this.hooks[name].tap(symbol, hook) + registerHook (name, hook, pluginName, types) { + const { valid, warnMsg } = assertTypes(hook, types) + if (valid) { + this.hooks[name].tap(pluginName, hook) + } else if (hook !== undefined) { + logger.warn( + `${chalk.gray(`[vuepress-plugin-${pluginName}]`)} ` + + `Invalid value for "option" ${chalk.cyan(name)}: ${warnMsg}` + ) } return this } - registerAPI (name, api) { - if (api) { + registerAPI (name, api, pluginName, types) { + const { valid, warnMsg } = assertTypes(api, types) + if (valid) { this.apis[name].push(api) + } else if (api !== undefined) { + logger.warn( + `${chalk.gray(`[vuepress-plugin-${pluginName}]`)} ` + + `Invalid value for "option" ${chalk.cyan(name)}: ${warnMsg}` + ) } return this } @@ -54,12 +68,12 @@ module.exports = class VuePressPlugin { pluginConfigs = Array.isArray(pluginConfigs) ? pluginConfigs : [pluginConfigs] - const [name, pluginOptions] = pluginConfigs - let plugin = resolvePlugin(name) + const [pluginRaw, pluginOptions] = pluginConfigs + let plugin = resolvePlugin(pluginRaw) if (typeof plugin === 'function') { plugin = plugin(pluginOptions) } - plugin = Object.assign(plugin, { name: inferPluginName(name, plugin) }) + plugin = Object.assign(plugin, { name: inferPluginName(pluginRaw, plugin) }) this.resolvePluginConfig(plugin) }) } @@ -79,18 +93,18 @@ module.exports = class VuePressPlugin { generated }) { this - .registerHook('ready', ready, name) - .registerHook('compiled', compiled, name) - .registerHook('updated', updated, name) - .registerHook('generated', generated, name) + .registerHook('ready', ready, name, [Function]) + .registerHook('compiled', compiled, name, [Function]) + .registerHook('updated', updated, name, [Function]) + .registerHook('generated', generated, name, [Function]) this - .registerAPI('client', client) - .registerAPI('chainWebpack', chainWebpack) - .registerAPI('enhanceDevServer', enhanceDevServer) - .registerAPI('extendMarkdown', extendMarkdown) - .registerAPI('enhanceAppFiles', enhanceAppFiles) - .registerAPI('outFiles', outFiles) - .registerAPI('extendPageData', extendPageData) + .registerAPI('client', client, name, [String]) + .registerAPI('chainWebpack', chainWebpack, name, [Function]) + .registerAPI('enhanceDevServer', enhanceDevServer, name, [Function]) + .registerAPI('extendMarkdown', extendMarkdown, name, [Function]) + .registerAPI('enhanceAppFiles', enhanceAppFiles, name, [Object]) + .registerAPI('outFiles', outFiles, name, [Object]) + .registerAPI('extendPageData', extendPageData, name, [Function]) } } diff --git a/lib/plugin-api/util.js b/lib/plugin-api/util.js index 9fe67c9c34..b053e67fd4 100644 --- a/lib/plugin-api/util.js +++ b/lib/plugin-api/util.js @@ -1,34 +1,81 @@ const logger = require('../util/logger') const chalk = require('chalk') -exports.resolvePlugin = function (pluginName) { - if (typeof pluginName === 'function' || typeof pluginName === 'object') { - return pluginName +exports.resolvePlugin = function (pluginRaw) { + if (typeof pluginRaw === 'function' || typeof pluginRaw === 'object') { + return pluginRaw } - if (typeof pluginName === 'string') { + if (typeof pluginRaw === 'string') { try { - return require(pluginName.startsWith('vuepress-plugin-') - ? pluginName - : `vuepress-plugin-${pluginName}` + return require(pluginRaw.startsWith('vuepress-plugin-') + ? pluginRaw + : `vuepress-plugin-${pluginRaw}` ) } catch (err) { - console.error(chalk.red(logger.error(`\n[vuepress] Cannot resolve plugin: ${pluginName}\n`, false))) + console.error(chalk.red(logger.error(`\n[vuepress] Cannot resolve plugin: ${pluginRaw}\n`, false))) throw new Error(err) } } - logger.warn(`\n[vuepress] Invalid plugin usage: ${chalk.yellow(pluginName)}\n`) + logger.warn(`\n[vuepress] Invalid plugin usage: ${chalk.yellow(pluginRaw)}\n`) } -exports.inferPluginName = function (pluginName, pluginConfig) { +exports.inferPluginName = function (pluginRaw, pluginConfig) { if (pluginConfig.name) { return pluginConfig.name } - if (typeof pluginName === 'string') { - if (pluginName.startsWith('vuepress-plugin-')) { - return pluginName.slice(16) + if (typeof pluginRaw === 'string') { + if (pluginRaw.startsWith('vuepress-plugin-')) { + return pluginRaw.slice(16) } - return pluginName + return pluginRaw } // ensure each plugin have a unique name. return Date.now().toString(16) } + +/** + * Get the raw type string of a value e.g. [object Object] + */ +const _toString = Object.prototype.toString + +exports.toRawType = function (value) { + return _toString.call(value).slice(8, -1) +} + +exports.getType = function (fn) { + const match = fn && fn.toString().match(/^\s*function (\w+)/) + return match ? match[1] : '' +} + +function toNaturalMultiTypesLanguage (types) { + const len = types.length + if (len === 1) { + return types.join('') + } + const rest = types.slice(0, len - 1) + const last = types[len - 1] + return rest.join(', ') + ' or ' + last +} + +exports.assertTypes = function (value, types) { + let valid + let warnMsg + const actualType = exports.toRawType(value) + const expectedTypes = [] + + for (const type of types) { + const expectedType = exports.getType(type) + expectedTypes.push(expectedType) + valid = actualType === expectedType + if (valid) break + } + + if (!valid) { + warnMsg = `expected a ${chalk.green(toNaturalMultiTypesLanguage(expectedTypes))}, but got ${chalk.yellow(actualType)}.` + } + + return { + valid, + warnMsg + } +} diff --git a/packages/vuepress-plugin-last-updated/index.js b/packages/vuepress-plugin-last-updated/index.js index 0945cd0d41..e1bc8f43e7 100644 --- a/packages/vuepress-plugin-last-updated/index.js +++ b/packages/vuepress-plugin-last-updated/index.js @@ -2,6 +2,7 @@ const path = require('path') const spawn = require('cross-spawn') module.exports = options => ({ + name: 'last-updated', client: path.resolve(__dirname, 'client.js'), extendPageData ({ filepath }) { return { From 5b00b0281dbbc5c7278ea06eaecaa1e5f0d384be Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Mon, 4 Jun 2018 00:31:14 +0800 Subject: [PATCH 005/242] feat: support enhanceAppFiles API. --- docs/.vuepress/components/demo-1.vue | 2 +- docs/.vuepress/config.js | 11 +++- lib/app/app.js | 8 +-- lib/plugin-api/api/AbstractAPI.js | 18 ++++++ lib/plugin-api/api/EnhanceAppFiles.js | 57 +++++++++++++++++++ lib/plugin-api/api/ExtendPageData.js | 14 +++++ lib/plugin-api/api/instantiateAPI.js | 14 +++++ lib/plugin-api/index.js | 13 +++-- lib/plugin-api/util.js | 4 +- lib/prepare/index.js | 5 ++ lib/prepare/resolveOptions.js | 10 +--- lib/prepare/util.js | 4 +- .../vuepress-plugin-last-updated/index.js | 2 + packages/vuepress-plugin-test/enhanceApp.js | 1 + packages/vuepress-plugin-test/index.js | 20 +++++++ 15 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 lib/plugin-api/api/AbstractAPI.js create mode 100644 lib/plugin-api/api/EnhanceAppFiles.js create mode 100644 lib/plugin-api/api/ExtendPageData.js create mode 100644 lib/plugin-api/api/instantiateAPI.js create mode 100644 packages/vuepress-plugin-test/enhanceApp.js create mode 100644 packages/vuepress-plugin-test/index.js diff --git a/docs/.vuepress/components/demo-1.vue b/docs/.vuepress/components/demo-1.vue index f1dfb581c5..0c6dc47718 100644 --- a/docs/.vuepress/components/demo-1.vue +++ b/docs/.vuepress/components/demo-1.vue @@ -5,7 +5,7 @@ + + diff --git a/packages/vuepress-translation-comparison/client.js b/packages/vuepress-translation-comparison/client.js new file mode 100644 index 0000000000..671533f4fd --- /dev/null +++ b/packages/vuepress-translation-comparison/client.js @@ -0,0 +1,5 @@ +import TranslationHelper from './TranslationHelper.vue' + +export default ({ Vue }) => { + Vue.component('TranslationHelper', TranslationHelper) +} diff --git a/packages/vuepress-translation-comparison/index.js b/packages/vuepress-translation-comparison/index.js new file mode 100644 index 0000000000..b131eed78e --- /dev/null +++ b/packages/vuepress-translation-comparison/index.js @@ -0,0 +1,14 @@ +module.exports = (options, context) => ({ + name: 'translation-comparison', + clientOnly: true, + enhanceAppFiles: [ + context.resolve(__dirname, 'client.js') + ], + additionalPages: [ + { + override: false, // will throw warning when '/translation/' has existed + route: '/translation/', + path: context.resolve(__dirname, 'translation.md') + } + ] +}) diff --git a/packages/vuepress-translation-comparison/translation.md b/packages/vuepress-translation-comparison/translation.md new file mode 100644 index 0000000000..0b6e6dc4eb --- /dev/null +++ b/packages/vuepress-translation-comparison/translation.md @@ -0,0 +1,3 @@ +--- +layout: TranslationHelper +--- From 3b16c5c37cbbf85ef4ba7ecb319f4ee1e16fcb33 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Thu, 14 Jun 2018 23:13:45 +0800 Subject: [PATCH 027/242] feat: support spearate "loadComponent" util --- lib/app/util.js | 7 ------- lib/prepare/codegen.js | 23 +++++++++++++++++++---- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/app/util.js b/lib/app/util.js index 2d6f62b5d3..c11172240e 100644 --- a/lib/app/util.js +++ b/lib/app/util.js @@ -17,10 +17,3 @@ export function findPageForPath (pages, path) { frontmatter: {} } } - -// export function loadPage (key) { -// return import(${JSON.stringify(filepath)}).then(comp => { -// Vue.component(${JSON.stringify(componentName)}, comp.default) -// next() -// }) -// } diff --git a/lib/prepare/codegen.js b/lib/prepare/codegen.js index 0978445e36..1997b5cf9d 100644 --- a/lib/prepare/codegen.js +++ b/lib/prepare/codegen.js @@ -21,19 +21,33 @@ exports.pathsToModuleCode = function (files) { return code } +exports.getPageComponentsLoadingFile = function (pages) { + let code = 'const _l = {}\n' + + code += pages.map(({ filepath, key }) => { + return `_l['${key}'] = () => import('${filepath}')` + }).join('\n') + + code += `\n\nexport default function loadComponent(key) { + return _l[key]() +}\n` + return code +} + exports.genRoutesFile = async function ({ siteData: { pages }, plugin }) { - function genRoute ({ filepath, path: pagePath, key: componentName }, index) { + await writeTemp('components-loader.js', exports.getPageComponentsLoadingFile(pages)) + + function genRoute ({ path: pagePath, key: componentName }, index) { let code = ` { name: ${JSON.stringify(componentName)}, path: ${JSON.stringify(pagePath)}, component: ThemeLayout, beforeEnter: (to, from, next) => { - loadPageComponent("v-6e489b82c1bb8").then(next) - import(${JSON.stringify(filepath)}).then(comp => { + loadComponent(${JSON.stringify(componentName)}).then(comp => { Vue.component(${JSON.stringify(componentName)}, comp.default) next() }) @@ -80,7 +94,8 @@ exports.genRoutesFile = async function ({ `import Vue from 'vue'\n` + `import ThemeLayout from '@themeLayout'\n` + `import ThemeNotFound from '@themeNotFound'\n` + - `import { injectMixins, loadPageComponent } from '@app/util'\n` + + `import { injectMixins } from '@app/util'\n` + + `import loadComponent from '@temp/components-loader'\n` + `import rootMixins from '@temp/root-mixins'\n\n` + `injectMixins(ThemeLayout, rootMixins)\n` + `injectMixins(ThemeNotFound, rootMixins)\n\n` + From d210ec035a442f3c59842262f9bbdb7654be1f6e Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Thu, 14 Jun 2018 23:40:12 +0800 Subject: [PATCH 028/242] refactor: use async components to simplify code --- lib/prepare/codegen.js | 27 +++---------------- .../TranslationHelper.vue | 3 --- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/lib/prepare/codegen.js b/lib/prepare/codegen.js index 1997b5cf9d..c496d5ca33 100644 --- a/lib/prepare/codegen.js +++ b/lib/prepare/codegen.js @@ -21,37 +21,16 @@ exports.pathsToModuleCode = function (files) { return code } -exports.getPageComponentsLoadingFile = function (pages) { - let code = 'const _l = {}\n' - - code += pages.map(({ filepath, key }) => { - return `_l['${key}'] = () => import('${filepath}')` - }).join('\n') - - code += `\n\nexport default function loadComponent(key) { - return _l[key]() -}\n` - return code -} - exports.genRoutesFile = async function ({ siteData: { pages }, plugin }) { - await writeTemp('components-loader.js', exports.getPageComponentsLoadingFile(pages)) - function genRoute ({ path: pagePath, key: componentName }, index) { let code = ` { name: ${JSON.stringify(componentName)}, path: ${JSON.stringify(pagePath)}, - component: ThemeLayout, - beforeEnter: (to, from, next) => { - loadComponent(${JSON.stringify(componentName)}).then(comp => { - Vue.component(${JSON.stringify(componentName)}, comp.default) - next() - }) - } + component: ThemeLayout }` const dncodedPath = decodeURIComponent(pagePath) @@ -94,11 +73,11 @@ exports.genRoutesFile = async function ({ `import Vue from 'vue'\n` + `import ThemeLayout from '@themeLayout'\n` + `import ThemeNotFound from '@themeNotFound'\n` + - `import { injectMixins } from '@app/util'\n` + - `import loadComponent from '@temp/components-loader'\n` + + `import { injectMixins, loadComponent } from '@app/util'\n` + `import rootMixins from '@temp/root-mixins'\n\n` + `injectMixins(ThemeLayout, rootMixins)\n` + `injectMixins(ThemeNotFound, rootMixins)\n\n` + + `${pages.map(({ filepath, key }) => `Vue.component('${key}', () => import('${filepath}'))`).join('\n')}\n\n` + `export const routes = [${pages.map(genRoute).join(',')}${notFoundRoute}\n]` ) } diff --git a/packages/vuepress-translation-comparison/TranslationHelper.vue b/packages/vuepress-translation-comparison/TranslationHelper.vue index e23ad2c5a9..e6b20e004a 100644 --- a/packages/vuepress-translation-comparison/TranslationHelper.vue +++ b/packages/vuepress-translation-comparison/TranslationHelper.vue @@ -20,9 +20,6 @@ export default { currentPath: '/' } }, - created () { - console.log(this.key) - }, computed: { key () { return this.currentPage.key From 4a4f8ed01cd54337d272f04d1ba9c378ffd7cff5 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Fri, 15 Jun 2018 00:10:22 +0800 Subject: [PATCH 029/242] style: change ".content" to "#content" --- lib/default-theme/NotFound.vue | 2 +- lib/default-theme/styles/code.styl | 4 ++-- lib/default-theme/styles/mobile.styl | 2 +- lib/default-theme/styles/theme.styl | 8 ++++---- lib/webpack/markdownLoader.js | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/default-theme/NotFound.vue b/lib/default-theme/NotFound.vue index 6aefe797c4..ed2c0e27c5 100644 --- a/lib/default-theme/NotFound.vue +++ b/lib/default-theme/NotFound.vue @@ -1,6 +1,6 @@