Skip to content

Commit 9734a58

Browse files
shigmaulivz
authored andcommitted
feat($markdown): markdown plugin (close: #585) (#1422)
1 parent 3b14375 commit 9734a58

File tree

8 files changed

+126
-38
lines changed

8 files changed

+126
-38
lines changed

packages/@vuepress/core/lib/node/plugin-api/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
*/
66

77
const instantiateOption = require('./override/instantiateOption')
8-
const { flattenPlugin, normalizePluginsConfig } = require('./util')
8+
const { flattenPlugin } = require('./util')
99
const { PLUGIN_OPTION_MAP } = require('./constants')
1010
const {
1111
moduleResolver: { getPluginResolver },
1212
datatypes: { assertTypes, isPlainObject },
13-
logger, chalk
13+
logger, chalk, normalizeConfig
1414
} = require('@vuepress/shared-utils')
1515

1616
/**
@@ -136,7 +136,7 @@ module.exports = class PluginAPI {
136136
*/
137137

138138
useByPluginsConfig (pluginsConfig) {
139-
pluginsConfig = normalizePluginsConfig(pluginsConfig)
139+
pluginsConfig = normalizeConfig(pluginsConfig)
140140
pluginsConfig.forEach(([pluginRaw, pluginOptions]) => {
141141
this.use(pluginRaw, pluginOptions)
142142
})

packages/@vuepress/core/lib/node/plugin-api/util.js

-31
Original file line numberDiff line numberDiff line change
@@ -57,34 +57,3 @@ exports.flattenPlugin = function (
5757
$$options: pluginOptions /* used for test */
5858
})
5959
}
60-
61-
/**
62-
* Normalize plugins config in `.vuepress/config.js`
63-
*
64-
* @param pluginsConfig
65-
*/
66-
67-
exports.normalizePluginsConfig = function (pluginsConfig) {
68-
const { valid, warnMsg } = assertTypes(pluginsConfig, [Object, Array])
69-
if (!valid) {
70-
if (pluginsConfig !== undefined) {
71-
logger.warn(
72-
`[${chalk.gray('config')}] `
73-
+ `Invalid value for "plugin" field : ${warnMsg}`
74-
)
75-
}
76-
pluginsConfig = []
77-
return pluginsConfig
78-
}
79-
80-
if (Array.isArray(pluginsConfig)) {
81-
pluginsConfig = pluginsConfig.map(item => {
82-
return Array.isArray(item) ? item : [item]
83-
})
84-
} else if (typeof pluginsConfig === 'object') {
85-
pluginsConfig = Object.keys(pluginsConfig).map(item => {
86-
return [item, pluginsConfig[item]]
87-
})
88-
}
89-
return pluginsConfig
90-
}

packages/@vuepress/markdown/index.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ const snippetPlugin = require('./lib/snippet')
1818
const tocPlugin = require('./lib/tableOfContents')
1919
const emojiPlugin = require('markdown-it-emoji')
2020
const anchorPlugin = require('markdown-it-anchor')
21-
const { slugify: _slugify, logger, chalk, hash } = require('@vuepress/shared-utils')
21+
const {
22+
slugify: _slugify,
23+
logger, chalk, hash, normalizeConfig,
24+
moduleResolver: { getMarkdownItResolver }
25+
} = require('@vuepress/shared-utils')
2226

2327
/**
2428
* Create markdown by config.
@@ -29,11 +33,14 @@ module.exports = (markdown = {}) => {
2933
externalLinks,
3034
anchor,
3135
toc,
36+
plugins,
3237
lineNumbers,
3338
beforeInstantiate,
3439
afterInstantiate
3540
} = markdown
3641

42+
const resolver = getMarkdownItResolver()
43+
3744
// allow user config slugify
3845
const slugify = markdown.slugify || _slugify
3946

@@ -100,6 +107,16 @@ module.exports = (markdown = {}) => {
100107

101108
const md = config.toMd(require('markdown-it'), markdown)
102109

110+
const pluginsConfig = normalizeConfig(plugins || [])
111+
pluginsConfig.forEach(([pluginRaw, pluginOptions]) => {
112+
const plugin = resolver.resolve(pluginRaw)
113+
if (plugin.entry) {
114+
md.use(plugin.entry, pluginOptions)
115+
} else {
116+
// TODO: error handling
117+
}
118+
})
119+
103120
afterInstantiate && afterInstantiate(md)
104121

105122
// override parse to allow cache

packages/@vuepress/shared-utils/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as isIndexFile from './isIndexFile'
1414
import logger from './logger'
1515
import * as moduleLoader from './moduleLoader'
1616
import * as moduleResolver from './moduleResolver'
17+
import normalizeConfig from './normalizeConfig'
1718
import * as parseEmojis from './parseEmojis'
1819
import parseFrontmatter from './parseFrontmatter'
1920
import parseHeaders from './parseHeaders'
@@ -50,6 +51,7 @@ export {
5051
logger,
5152
moduleLoader,
5253
moduleResolver,
54+
normalizeConfig,
5355
parseEmojis,
5456
parseFrontmatter,
5557
parseHeaders,

packages/@vuepress/shared-utils/src/moduleResolver.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,12 @@ class ModuleResolver {
7676
this.allowedTypes = allowedTypes
7777
this.load = load
7878
this.cwd = cwd || process.cwd()
79-
this.nonScopePrefix = `${org}-${type}-`
80-
this.scopePrefix = `@${org}/${type}-`
79+
if (org) {
80+
this.nonScopePrefix = `${org}-${type}-`
81+
this.scopePrefix = `@${org}/${type}-`
82+
} else {
83+
this.nonScopePrefix = `${type}-`
84+
}
8185
this.typePrefixLength = type.length + 1
8286
/* - */
8387
this.prefixSlicePosition = this.typePrefixLength + org.length + 1
@@ -197,7 +201,7 @@ class ModuleResolver {
197201
const pkg = resolveScopePackage(req)
198202
if (pkg) {
199203
// speicial handling for default org.
200-
if (pkg.org === this.org) {
204+
if (this.org && pkg.org === this.org) {
201205
shortcut = pkg.name.startsWith(`${this.type}-`)
202206
? pkg.name.slice(this.typePrefixLength)
203207
: pkg.name
@@ -265,6 +269,10 @@ export function resolveScopePackage (name: string) {
265269
}
266270
}
267271

272+
export const getMarkdownItResolver = (cwd: string) => new ModuleResolver(
273+
'markdown-it', '', [String, Function], true /* load module */, cwd
274+
)
275+
268276
export const getPluginResolver = (cwd: string): ModuleResolver => new ModuleResolver(
269277
'plugin', 'vuepress', [String, Function, Object], true /* load module */, cwd
270278
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { assertTypes } from './datatypes'
2+
import logger from './logger'
3+
import chalk from 'chalk'
4+
5+
export default function normalizeConfig (pluginsConfig: any) {
6+
const { valid, warnMsg } = assertTypes(pluginsConfig, [Object, Array])
7+
if (!valid) {
8+
if (pluginsConfig !== undefined) {
9+
logger.warn(
10+
`[${chalk.gray('config')}] `
11+
+ `Invalid value for "plugin" field : ${warnMsg}`
12+
)
13+
}
14+
pluginsConfig = []
15+
return pluginsConfig
16+
}
17+
18+
if (Array.isArray(pluginsConfig)) {
19+
pluginsConfig = pluginsConfig.map(item => {
20+
return Array.isArray(item) ? item : [item]
21+
})
22+
} else if (typeof pluginsConfig === 'object') {
23+
pluginsConfig = Object.keys(pluginsConfig).map(item => {
24+
return [item, pluginsConfig[item]]
25+
})
26+
}
27+
return pluginsConfig
28+
}

packages/docs/docs/config/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,38 @@ This attribute will control the behaviour of `[[TOC]]`. It contains the followin
240240

241241
We also provide a [global component TOC](../guide/using-vue.md#toc) which allows for more free control by passing props directly to `<TOC>`.
242242

243+
### markdown.plugins
244+
245+
You can install any markdown-it plugins through `markdown.plugins` option. It is similar with [using VuePress plugins](../plugin/using-a-plugin.html#using-a-plugin). You can either use Babel style or object style. The `markdown-it-` prefix is optional and can omit in the list.
246+
247+
``` js
248+
module.exports = {
249+
markdown: {
250+
plugins: [
251+
'@org/foo', // equals to @org/markdown-it-foo if exists
252+
['markdown-it-bar', {
253+
// provide options here
254+
}]
255+
]
256+
}
257+
}
258+
```
259+
260+
or
261+
262+
``` js
263+
module.exports = {
264+
markdown: {
265+
plugins: {
266+
'@org/foo': {}
267+
'markdown-it-bar': {
268+
// provide options here
269+
}
270+
}
271+
}
272+
}
273+
```
274+
243275
### markdown.extendMarkdown
244276

245277
- Type: `Function`

packages/docs/docs/zh/config/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,38 @@ VuePress 提供了一种添加额外样式的简便方法。你可以创建一
232232

233233
此外,我们还提供了[全局组件 TOC](../guide/using-vue.md#toc),可以通过直接向 `<TOC>` 传递属性实现更加自由的控制。
234234

235+
### markdown.plugins
236+
237+
你可以使用 `markdown.plugins` 来安装 markdown-it 插件。它的使用方法与[安装一个 VuePress 插件](../plugin/using-a-plugin.html#using-a-plugin)类似。你可以使用 Babel 语法或对象语法。`markdown-it-` 前缀同样是可以忽略的。
238+
239+
``` js
240+
module.exports = {
241+
markdown: {
242+
plugins: [
243+
'@org/foo', // 等价于 @org/markdown-it-foo,如果对应的包存在
244+
['markdown-it-bar', {
245+
// 提供你的选项
246+
}]
247+
]
248+
}
249+
}
250+
```
251+
252+
or
253+
254+
``` js
255+
module.exports = {
256+
markdown: {
257+
plugins: {
258+
'@org/foo': {}
259+
'markdown-it-bar': {
260+
// 提供你的选项
261+
}
262+
}
263+
}
264+
}
265+
```
266+
235267
### markdown.extendMarkdown
236268

237269
- 类型: `Function`

0 commit comments

Comments
 (0)