提交 46e1992f 编写于 作者: U ULIVZ

feat: init plugin

上级 cd8ee42f
......@@ -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,
......
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)
}
}
}
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)
}
}
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)
}
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
}
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册