Skip to content

Commit 4f26102

Browse files
committed
feat: support 'dynamicClientCode' option
1. Move global components registration to a single plugin 'vuepress-plugin-register-global-components' 2. Support register global theme components (`${themePath}/components`) (#345)
1 parent af14e4b commit 4f26102

File tree

10 files changed

+91
-52
lines changed

10 files changed

+91
-52
lines changed

lib/app/app.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import store from './store'
99
import { routes } from '@temp/routes'
1010
import { siteData } from '@temp/siteData'
1111
import appEnhancers from '@temp/appEnhancers.js'
12+
import '@temp/dynamicClientCode.js'
1213

1314
// suggest dev server restart on base change
1415
if (module.hot) {

lib/plugin-api/constans.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const ENHANCE_APP_FILES = 'enhanceAppFiles'
1010
const OUT_FILES = 'outFiles'
1111
const EXTEND_PAGE_DATA = 'extendPageData'
1212
const EXTEND_MARKDOWN = 'extendMarkdown'
13+
const DYNAMIC_CLIENT_CODE = 'dynamicClientCode'
1314

1415
const HOOK = {
1516
READY,
@@ -25,7 +26,8 @@ const OPTION = {
2526
ENHANCE_APP_FILES,
2627
OUT_FILES,
2728
EXTEND_PAGE_DATA,
28-
EXTEND_MARKDOWN
29+
EXTEND_MARKDOWN,
30+
DYNAMIC_CLIENT_CODE
2931
}
3032

3133
exports.HOOK = HOOK

lib/plugin-api/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ module.exports = class Plugin {
8888
ready,
8989
compiled,
9090
updated,
91-
generated
91+
generated,
92+
dynamicClientCode
9293
}) {
9394
logger.tip(`\nApply plugin ${chalk.cyan(name)}...`)
9495

@@ -106,5 +107,6 @@ module.exports = class Plugin {
106107
.registerOption(OPTION.EXTEND_PAGE_DATA, extendPageData, name, [Function])
107108
.registerOption(OPTION.ENHANCE_APP_FILES, enhanceAppFiles, name, [Array, Function])
108109
.registerOption(OPTION.OUT_FILES, outFiles, name, [Object])
110+
.registerOption(OPTION.DYNAMIC_CLIENT_CODE, dynamicClientCode, name, [Function])
109111
}
110112
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const Tapable = require('../core/Tapable')
2+
const { writeTemp } = require('../../prepare/util')
3+
4+
module.exports = class DynamicClientCodeOption extends Tapable {
5+
async run () {
6+
let code = ''
7+
for (const item of this.items) {
8+
const { value: fn, name: pluginName } = item
9+
const res = await fn()
10+
code += `
11+
/**
12+
* Generated by [vuepress-plugin-${pluginName}]"
13+
*/
14+
${res}\n\n
15+
`.trim()
16+
}
17+
await writeTemp('dynamicClientCode.js', code)
18+
}
19+
}

lib/plugin-api/option/instantiateOption.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const EnhanceAppFilesOption = require('./EnhanceAppFilesOption')
22
const ExtendPageDataOption = require('./ExtendPageDataOption')
3+
const DynamicClientCodeOption = require('./DynamicClientCodeOption')
34
const Tapable = require('../core/Tapable')
45

56
module.exports = function instantiateOption (name) {
@@ -8,6 +9,8 @@ module.exports = function instantiateOption (name) {
89
return new EnhanceAppFilesOption(name)
910
case 'extendPageData':
1011
return new ExtendPageDataOption(name)
12+
case 'dynamicClientCode':
13+
return new DynamicClientCodeOption(name)
1114

1215
default: return new Tapable(name)
1316
}

lib/prepare/codegen.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const path = require('path')
2-
const { fileToComponentName, resolveComponents } = require('./util')
32

43
exports.genRoutesFile = async function ({
54
siteData: { pages },
@@ -49,6 +48,7 @@ exports.genRoutesFile = async function ({
4948
}`
5049

5150
return (
51+
`import Vue from 'vue'\n` +
5252
`import ThemeLayout from '@themeLayout'\n` +
5353
`import ThemeNotFound from '@themeNotFound'\n` +
5454
`import { injectMixins } from '@app/util'\n` +
@@ -58,17 +58,3 @@ exports.genRoutesFile = async function ({
5858
`export const routes = [${pages.map(genRoute).join(',')}${notFoundRoute}\n]`
5959
)
6060
}
61-
62-
exports.genComponentRegistrationFile = async function ({ sourceDir }) {
63-
function genImport (file) {
64-
const name = fileToComponentName(file)
65-
const baseDir = path.resolve(sourceDir, '.vuepress/components')
66-
const absolutePath = path.resolve(baseDir, file)
67-
const code = `Vue.component(${JSON.stringify(name)}, () => import(${JSON.stringify(absolutePath)}))`
68-
return code
69-
}
70-
71-
const components = (await resolveComponents(sourceDir)) || []
72-
return `import Vue from 'vue'\n` + components.map(genImport).join('\n')
73-
}
74-

lib/prepare/index.js

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,33 @@ const fs = require('fs-extra')
33
const resolveOptions = require('./resolveOptions')
44
const resolveSiteData = require('./resolveSiteData')
55
const resolvePlugin = require('./resolvePlugin')
6-
const { genRoutesFile, genComponentRegistrationFile } = require('./codegen')
6+
const { genRoutesFile } = require('./codegen')
77
const { writeTemp } = require('./util')
88

99
module.exports = async function prepare (sourceDir) {
1010
// 1. load options
1111
const options = await resolveOptions(sourceDir)
12-
const { siteConfig, markdown } = options
12+
const { markdown } = options
1313

1414
// 2. resolve plugin
15-
const plugin = resolvePlugin(siteConfig.plugins, options)
15+
const plugin = resolvePlugin(options)
1616
options.plugin = plugin
1717

18-
// 3. Apply plugin options to extend makrdown.
18+
// 3. Apply plugin options to extend markdown.
1919
plugin.options.extendMarkdown.run(markdown)
20+
plugin.options.dynamicClientCode.run()
2021

2122
// 4. resolve siteData
2223
// SiteData must be resolved after the plugin initialization
2324
// because plugins can be able to extend the sitedata.
2425
options.siteData = await resolveSiteData(options)
2526
Object.freeze(options)
2627

27-
await plugin.hooks.ready.run(options)
28+
await plugin.hooks.ready.run()
2829

29-
// 5. generate routes & user components registration code
30+
// 5. generate routes code
3031
const routesCode = await genRoutesFile(options)
31-
const componentCode = await genComponentRegistrationFile(options)
32-
33-
await writeTemp('routes.js', [
34-
componentCode,
35-
routesCode
36-
].join('\n'))
32+
await writeTemp('routes.js', routesCode)
3733

3834
// 6. generate siteData
3935
const dataCode = `export const siteData = ${JSON.stringify(options.siteData, null, 2)}`

lib/prepare/resolvePlugin.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1+
const path = require('path')
12
const Plugin = require('../plugin-api')
23
const PluginContext = require('../plugin-api/context')
34

45
// built-in plugins
56
const lastUpdatedPlugin = require('../../packages/vuepress-plugin-last-updated')
67
const enhanceApp = require('../../packages/vuepree-plugin-enhance-app')
8+
const registerGlobalComponents = require('../../packages/vuepress-plugin-register-global-components')
79

8-
module.exports = function (pluginConfigs, context) {
9-
const pluginContext = new PluginContext(context)
10+
module.exports = function (options) {
11+
const { siteConfig, sourceDir, themePath } = options
12+
const pluginContext = new PluginContext(options)
1013
const plugin = new Plugin(pluginContext)
1114

1215
plugin
1316
.use(lastUpdatedPlugin)
1417
.use(enhanceApp)
15-
.useByConfigs(pluginConfigs)
18+
.use(registerGlobalComponents, {
19+
baseDirs: [
20+
path.resolve(sourceDir, '.vuepress/components'),
21+
path.resolve(themePath, 'components')
22+
]
23+
})
24+
.useByConfigs(siteConfig.plugins)
1625

1726
return plugin
1827
}

lib/prepare/util.js

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const path = require('path')
22
const fs = require('fs-extra')
3-
const globby = require('globby')
43

54
const tempPath = path.resolve(__dirname, '../app/.temp')
65
fs.ensureDirSync(tempPath)
@@ -41,29 +40,10 @@ exports.fileToPath = function (file) {
4140
}
4241
}
4342

44-
exports.fileToComponentName = function (file) {
45-
let normalizedName = file
46-
.replace(/\/|\\/g, '-')
47-
.replace(extRE, '')
48-
if (exports.isIndexFile(file)) {
49-
normalizedName = normalizedName.replace(/readme$/i, 'index')
50-
}
51-
const pagePrefix = /\.md$/.test(file) ? `page-` : ``
52-
return `${pagePrefix}${normalizedName}`
53-
}
54-
5543
exports.isIndexFile = function (file) {
5644
return indexRE.test(file)
5745
}
5846

59-
exports.resolveComponents = async function (sourceDir) {
60-
const componentDir = path.resolve(sourceDir, '.vuepress/components')
61-
if (!fs.existsSync(componentDir)) {
62-
return
63-
}
64-
return exports.sort(await globby(['**/*.vue'], { cwd: componentDir }))
65-
}
66-
6747
exports.sort = function (arr) {
6848
return arr.sort((a, b) => {
6949
if (a < b) return -1
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const fs = require('fs-extra')
2+
const path = require('path')
3+
const globby = require('globby')
4+
5+
function fileToComponentName (file) {
6+
return file
7+
.replace(/\/|\\/g, '-')
8+
.replace(/\.vue$/, '')
9+
}
10+
11+
async function resolveComponents (componentDir) {
12+
if (!fs.existsSync(componentDir)) {
13+
return
14+
}
15+
return (await globby(['**/*.vue'], { cwd: componentDir }))
16+
}
17+
18+
module.exports = (options, context) => ({
19+
name: 'register-global-components',
20+
21+
async dynamicClientCode () {
22+
const { baseDirs } = options
23+
// const { sourceDir } = context
24+
25+
function genImport (baseDir, file) {
26+
const name = fileToComponentName(file)
27+
const absolutePath = path.resolve(baseDir, file)
28+
// const baseDir = path.resolve(sourceDir, '.vuepress/components')
29+
const code = `Vue.component(${JSON.stringify(name)}, () => import(${JSON.stringify(absolutePath)}))`
30+
return code
31+
}
32+
33+
let code = ''
34+
for (const baseDir of baseDirs) {
35+
const files = await resolveComponents(baseDir) || []
36+
code += files.map(file => genImport(baseDir, file)).join('\n') + '\n\n'
37+
}
38+
39+
return `import Vue from 'vue'\n` + code
40+
}
41+
})

0 commit comments

Comments
 (0)