Skip to content

Commit 6056e37

Browse files
committedJul 6, 2022
feat(markdown): support frontmatter options
- use markdown frontmatter plugin - remove gray-matter usage
1 parent 63289b0 commit 6056e37

19 files changed

+303
-275
lines changed
 

‎docs/reference/config.md

+60
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,20 @@ Since VuePress will load temp files during dev and build, the temp directory sho
354354

355355
- Type: `AnchorPluginOptions | false`
356356

357+
- Default:
358+
359+
```ts
360+
const defaultOptions = {
361+
level: [1, 2, 3, 4, 5, 6],
362+
permalink: anchorPlugin.permalink.ariaHidden({
363+
class: 'header-anchor',
364+
symbol: '#',
365+
space: true,
366+
placement: 'before',
367+
}),
368+
}
369+
```
370+
357371
- Details:
358372

359373
Options for [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor).
@@ -488,10 +502,48 @@ You should not configure it unless you understand what it is for.
488502
- Also see:
489503
- [Guide > Markdown > Syntax Extensions > Emoji](../guide/markdown.md#emoji)
490504

505+
### markdown.frontmatter
506+
507+
- Type: `FrontmatterPluginOptions | false`
508+
509+
- Default:
510+
511+
```ts
512+
const defaultOptions = {
513+
grayMatterOptions: {
514+
excerpt: true,
515+
excerpt_separator: '<!-- more -->',
516+
},
517+
}
518+
```
519+
520+
- Details:
521+
522+
Options for [@mdit-vue/plugin-frontmatter](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter).
523+
524+
Set to `false` to disable this plugin.
525+
526+
- Also see:
527+
- [Guide > Page > Frontmatter](../guide/page.md#frontmatter)
528+
- [Node API > Page Properties > frontmatter](./node-api.md#frontmatter)
529+
- [Node API > Page Properties > excerpt](./node-api.md#excerpt)
530+
531+
::: danger
532+
You should not configure it unless you understand what it is for.
533+
:::
534+
491535
### markdown.headers
492536

493537
- Type: `HeadersPluginOptions | false`
494538

539+
- Default:
540+
541+
```ts
542+
const defaultOptions = {
543+
level: [2, 3],
544+
}
545+
```
546+
495547
- Details:
496548

497549
Options for [@mdit-vue/plugin-headers](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers).
@@ -601,6 +653,14 @@ You should not configure it unless you understand what it is for.
601653

602654
- Type: `TocPluginOptions | false`
603655

656+
- Default:
657+
658+
```ts
659+
const defaultOptions = {
660+
level: [2, 3],
661+
}
662+
```
663+
604664
- Details:
605665

606666
Options for [@mdit-vue/plugin-toc](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc).

‎docs/zh/guide/migration.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ VuePress v2 的核心思想和流程是和 v1 一致的,但 v2 API 经过了
146146
+ }
147147
```
148148

149-
请参考 [Guide > Bundler](./bundler.md)
149+
请参考 [指南 > Bundler](./bundler.md)
150150

151151
### Frontmatter 变更
152152

‎docs/zh/reference/config.md

+60
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,20 @@ VuePress 在开发和构建时会加载临时文件,因此临时文件目录
353353

354354
- 类型: `AnchorPluginOptions | false`
355355

356+
- 默认值:
357+
358+
```ts
359+
const defaultOptions = {
360+
level: [1, 2, 3, 4, 5, 6],
361+
permalink: anchorPlugin.permalink.ariaHidden({
362+
class: 'header-anchor',
363+
symbol: '#',
364+
space: true,
365+
placement: 'before',
366+
}),
367+
}
368+
```
369+
356370
- 详情:
357371

358372
[markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) 的配置项。
@@ -487,10 +501,48 @@ VuePress 在开发和构建时会加载临时文件,因此临时文件目录
487501
- 参考:
488502
- [指南 > Markdown > 语法扩展 > Emoji](../guide/markdown.md#emoji)
489503

504+
### markdown.frontmatter
505+
506+
- 类型: `FrontmatterPluginOptions | false`
507+
508+
- 默认值:
509+
510+
```ts
511+
const defaultOptions = {
512+
grayMatterOptions: {
513+
excerpt: true,
514+
excerpt_separator: '<!-- more -->',
515+
},
516+
}
517+
```
518+
519+
- 详情:
520+
521+
[@mdit-vue/plugin-frontmatter](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter) 插件的配置项。
522+
523+
设置为 `false` 可以禁用该插件。
524+
525+
- 参考:
526+
- [指南 > 页面 > Frontmatter](../guide/page.md#frontmatter)
527+
- [Node API > Page 属性 > frontmatter](./node-api.md#frontmatter)
528+
- [Node API > Page 属性 > excerpt](./node-api.md#excerpt)
529+
530+
::: danger
531+
除非你了解它的用途,否则你不应该设置该配置项。
532+
:::
533+
490534
### markdown.headers
491535

492536
- 类型: `HeadersPluginOptions | false`
493537

538+
- 默认值:
539+
540+
```ts
541+
const defaultOptions = {
542+
level: [2, 3],
543+
}
544+
```
545+
494546
- 详情:
495547

496548
[@mdit-vue/plugin-headers](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers) 插件的配置项。
@@ -600,6 +652,14 @@ VuePress 在开发和构建时会加载临时文件,因此临时文件目录
600652

601653
- 类型: `TocPluginOptions | false`
602654

655+
- 默认值:
656+
657+
```ts
658+
const defaultOptions = {
659+
level: [2, 3],
660+
}
661+
```
662+
603663
- 详情:
604664

605665
[@mdit-vue/plugin-toc](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc) 插件的配置项。

‎packages/@vuepress/core/__tests__/page/renderPageContent.spec.ts

+95-6
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ describe('core > page > renderPageContent', () => {
1414
const resolved = await renderPageContent({
1515
app,
1616
content: 'foobar',
17-
frontmatter: {},
1817
filePath: app.dir.source('foo.md'),
1918
filePathRelative: 'foo.md',
19+
options: {},
2020
})
2121

2222
expect(resolved).toEqual({
2323
contentRendered: '<p>foobar</p>\n',
2424
deps: [],
25+
excerpt: '',
26+
frontmatter: {},
2527
headers: [],
2628
links: [],
2729
sfcBlocks: [],
@@ -34,11 +36,13 @@ describe('core > page > renderPageContent', () => {
3436
const resolved = await renderPageContent({
3537
app,
3638
content: '# title in header',
37-
frontmatter: {
38-
title: 'title in frontmatter',
39-
},
4039
filePath: null,
4140
filePathRelative: null,
41+
options: {
42+
frontmatter: {
43+
title: 'title in frontmatter',
44+
},
45+
},
4246
})
4347

4448
expect(resolved.title).toEqual('title in frontmatter')
@@ -48,9 +52,9 @@ describe('core > page > renderPageContent', () => {
4852
const resolved = await renderPageContent({
4953
app,
5054
content: '# title in header',
51-
frontmatter: {},
5255
filePath: null,
5356
filePathRelative: null,
57+
options: {},
5458
})
5559

5660
expect(resolved.title).toEqual('title in header')
@@ -60,12 +64,97 @@ describe('core > page > renderPageContent', () => {
6064
const resolved = await renderPageContent({
6165
app,
6266
content: '',
63-
frontmatter: {},
6467
filePath: null,
6568
filePathRelative: null,
69+
options: {},
6670
})
6771

6872
expect(resolved.title).toEqual('')
6973
})
7074
})
75+
76+
describe('page frontmatter', () => {
77+
it('should merge markdown frontmatter and options frontmatter', async () => {
78+
const resolved = await renderPageContent({
79+
app,
80+
content: `\
81+
---
82+
title: title in markdown frontmatter
83+
---
84+
`,
85+
filePath: null,
86+
filePathRelative: null,
87+
options: {
88+
frontmatter: {
89+
description: 'description in options frontmatter',
90+
},
91+
},
92+
})
93+
94+
expect(resolved.frontmatter).toEqual({
95+
title: 'title in markdown frontmatter',
96+
description: 'description in options frontmatter',
97+
})
98+
})
99+
100+
it('should use fields from markdown frontmatter first', async () => {
101+
const resolved = await renderPageContent({
102+
app,
103+
content: `\
104+
---
105+
title: title in markdown frontmatter
106+
---
107+
`,
108+
filePath: null,
109+
filePathRelative: null,
110+
options: {
111+
frontmatter: {
112+
title: 'title in options frontmatter',
113+
},
114+
},
115+
})
116+
117+
expect(resolved.frontmatter).toEqual({
118+
title: 'title in markdown frontmatter',
119+
})
120+
})
121+
})
122+
123+
describe('page excerpt', () => {
124+
it('should render page excerpt correctly', async () => {
125+
const resolved = await renderPageContent({
126+
app,
127+
content: `\
128+
---
129+
foo: foo
130+
bar: 1
131+
baz: true
132+
---
133+
134+
excerpt
135+
136+
<!-- more -->
137+
138+
foobar
139+
`,
140+
filePath: null,
141+
filePathRelative: null,
142+
options: {},
143+
})
144+
145+
expect(resolved.excerpt).toEqual('<p>excerpt</p>\n')
146+
})
147+
148+
it('should extract empty page excerpt', async () => {
149+
const resolved = await renderPageContent({
150+
app,
151+
content: '',
152+
filePath: null,
153+
filePathRelative: null,
154+
options: {},
155+
})
156+
157+
expect(resolved.excerpt).toEqual('')
158+
})
159+
})
71160
})

‎packages/@vuepress/core/__tests__/page/renderPageExcerpt.spec.ts

-24
This file was deleted.

‎packages/@vuepress/core/__tests__/page/resolvePageContent.spec.ts

-54
This file was deleted.

‎packages/@vuepress/core/__tests__/page/resolvePageFrontmatter.spec.ts

-38
This file was deleted.

‎packages/@vuepress/core/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
"@vuepress/markdown": "workspace:*",
3131
"@vuepress/shared": "workspace:*",
3232
"@vuepress/utils": "workspace:*",
33-
"gray-matter": "^4.0.3",
3433
"vue": "^3.2.37"
3534
},
3635
"publishConfig": {

‎packages/@vuepress/core/src/page/createPage.ts

+14-26
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import type { App, Page, PageOptions } from '../types'
22
import { inferPagePath } from './inferPagePath'
33
import { renderPageContent } from './renderPageContent'
4-
import { renderPageExcerpt } from './renderPageExcerpt'
54
import { resolvePageComponentInfo } from './resolvePageComponentInfo'
6-
import { resolvePageContent } from './resolvePageContent'
75
import { resolvePageDataInfo } from './resolvePageDataInfo'
86
import { resolvePageDate } from './resolvePageDate'
97
import { resolvePageFileContent } from './resolvePageFileContent'
108
import { resolvePageFilePath } from './resolvePageFilePath'
11-
import { resolvePageFrontmatter } from './resolvePageFrontmatter'
129
import { resolvePageHtmlInfo } from './resolvePageHtmlInfo'
1310
import { resolvePageKey } from './resolvePageKey'
1411
import { resolvePageLang } from './resolvePageLang'
@@ -31,35 +28,26 @@ export const createPage = async (
3128
})
3229

3330
// read the raw file content according to the absolute file path
34-
const contentRaw = await resolvePageFileContent({ filePath, options })
31+
const content = await resolvePageFileContent({ filePath, options })
3532

36-
// resolve content & frontmatter & raw excerpt from raw content
37-
const { content, frontmatterRaw, excerptRaw } = resolvePageContent({
38-
contentRaw,
39-
})
40-
41-
// resolve frontmatter from raw frontmatter and page options
42-
const frontmatter = resolvePageFrontmatter({ frontmatterRaw, options })
43-
44-
// render excerpt
45-
const excerpt = renderPageExcerpt({
33+
// render page content and extract information
34+
const {
35+
contentRendered,
36+
deps,
37+
excerpt,
38+
frontmatter,
39+
headers,
40+
links,
41+
sfcBlocks,
42+
title,
43+
} = await renderPageContent({
4644
app,
47-
excerptRaw,
45+
content,
4846
filePath,
4947
filePathRelative,
50-
frontmatter,
48+
options,
5149
})
5250

53-
// render page content and extract information
54-
const { contentRendered, deps, headers, links, sfcBlocks, title } =
55-
await renderPageContent({
56-
app,
57-
content,
58-
filePath,
59-
filePathRelative,
60-
frontmatter,
61-
})
62-
6351
// resolve route meta from frontmatter
6452
const routeMeta = resolvePageRouteMeta({ frontmatter })
6553

‎packages/@vuepress/core/src/page/index.ts

-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
export * from './createPage'
22
export * from './inferPagePath'
33
export * from './renderPageContent'
4-
export * from './renderPageExcerpt'
54
export * from './resolvePageComponentInfo'
6-
export * from './resolvePageContent'
75
export * from './resolvePageDataInfo'
86
export * from './resolvePageDate'
97
export * from './resolvePageFileContent'
108
export * from './resolvePageFilePath'
11-
export * from './resolvePageFrontmatter'
129
export * from './resolvePageHtmlInfo'
1310
export * from './resolvePageKey'
1411
export * from './resolvePageLang'

‎packages/@vuepress/core/src/page/renderPageContent.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,28 @@ import type {
33
MarkdownHeader,
44
MarkdownLink,
55
} from '@vuepress/markdown'
6-
import type { App, PageFrontmatter } from '../types'
6+
import type { App, PageFrontmatter, PageOptions } from '../types'
77

88
/**
99
* Render page content and extract related info
1010
*/
1111
export const renderPageContent = async ({
1212
app,
1313
content,
14-
frontmatter,
1514
filePath,
1615
filePathRelative,
16+
options,
1717
}: {
1818
app: App
1919
content: string
20-
frontmatter: PageFrontmatter
2120
filePath: string | null
2221
filePathRelative: string | null
22+
options: PageOptions
2323
}): Promise<{
2424
contentRendered: string
2525
deps: string[]
26+
excerpt: string
27+
frontmatter: PageFrontmatter
2628
headers: MarkdownHeader[]
2729
links: MarkdownLink[]
2830
sfcBlocks: string[]
@@ -32,13 +34,15 @@ export const renderPageContent = async ({
3234
base: app.options.base,
3335
filePath,
3436
filePathRelative,
35-
frontmatter,
37+
frontmatter: { ...options.frontmatter },
3638
}
3739

3840
const contentRendered = app.markdown.render(content, markdownEnv)
3941

4042
/* istanbul ignore next */
4143
const {
44+
excerpt = '',
45+
frontmatter = {},
4246
headers = [],
4347
importedFiles = [],
4448
links = [],
@@ -49,6 +53,8 @@ export const renderPageContent = async ({
4953
return {
5054
contentRendered,
5155
deps: importedFiles,
56+
excerpt,
57+
frontmatter,
5258
headers,
5359
links,
5460
sfcBlocks,

‎packages/@vuepress/core/src/page/renderPageExcerpt.ts

-28
This file was deleted.

‎packages/@vuepress/core/src/page/resolvePageContent.ts

-38
This file was deleted.

‎packages/@vuepress/core/src/page/resolvePageFrontmatter.ts

-16
This file was deleted.

‎packages/@vuepress/markdown/package.json

+7-6
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@
2626
"clean": "rimraf lib *.tsbuildinfo"
2727
},
2828
"dependencies": {
29-
"@mdit-vue/plugin-component": "^0.4.0",
30-
"@mdit-vue/plugin-headers": "^0.4.0",
31-
"@mdit-vue/plugin-sfc": "^0.4.0",
32-
"@mdit-vue/plugin-title": "^0.4.0",
33-
"@mdit-vue/plugin-toc": "^0.4.0",
34-
"@mdit-vue/shared": "^0.4.0",
29+
"@mdit-vue/plugin-component": "^0.5.0",
30+
"@mdit-vue/plugin-frontmatter": "^0.5.0",
31+
"@mdit-vue/plugin-headers": "^0.5.0",
32+
"@mdit-vue/plugin-sfc": "^0.5.0",
33+
"@mdit-vue/plugin-title": "^0.5.0",
34+
"@mdit-vue/plugin-toc": "^0.5.0",
35+
"@mdit-vue/shared": "^0.5.0",
3536
"@types/markdown-it": "^12.2.3",
3637
"@types/markdown-it-emoji": "^2.0.2",
3738
"@vuepress/shared": "workspace:*",

‎packages/@vuepress/markdown/src/markdown.ts

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
codePlugin,
77
componentPlugin,
88
emojiPlugin,
9+
frontmatterPlugin,
910
headersPlugin,
1011
importCodePlugin,
1112
linksPlugin,
@@ -18,6 +19,7 @@ import type {
1819
AssetsPluginOptions,
1920
CodePluginOptions,
2021
EmojiPluginOptions,
22+
FrontmatterPluginOptions,
2123
HeadersPluginOptions,
2224
ImportCodePluginOptions,
2325
LinksPluginOptions,
@@ -35,6 +37,7 @@ export const createMarkdown = ({
3537
code,
3638
component,
3739
emoji,
40+
frontmatter,
3841
headers,
3942
title,
4043
importCode,
@@ -108,6 +111,17 @@ export const createMarkdown = ({
108111
md.use(componentPlugin)
109112
}
110113

114+
if (frontmatter !== false) {
115+
md.use<FrontmatterPluginOptions>(frontmatterPlugin, {
116+
...frontmatter,
117+
grayMatterOptions: {
118+
excerpt: true,
119+
excerpt_separator: '<!-- more -->',
120+
...frontmatter?.grayMatterOptions,
121+
},
122+
})
123+
}
124+
111125
// replace relative link of assets with absolute link
112126
if (assets !== false) {
113127
md.use<AssetsPluginOptions>(assetsPlugin, assets)

‎packages/@vuepress/markdown/src/plugins/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from '@mdit-vue/plugin-component'
2+
export * from '@mdit-vue/plugin-frontmatter'
23
export * from '@mdit-vue/plugin-headers'
34
export * from '@mdit-vue/plugin-sfc'
45
export * from '@mdit-vue/plugin-title'

‎packages/@vuepress/markdown/src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
AssetsPluginOptions,
77
CodePluginOptions,
88
EmojiPluginOptions,
9+
FrontmatterPluginOptions,
910
HeadersPluginOptions,
1011
ImportCodePluginOptions,
1112
LinksPluginOptions,
@@ -21,6 +22,7 @@ export interface MarkdownOptions extends MarkdownIt.Options {
2122
code?: false | CodePluginOptions
2223
component?: false
2324
emoji?: false | EmojiPluginOptions
25+
frontmatter?: false | FrontmatterPluginOptions
2426
headers?: false | HeadersPluginOptions
2527
title?: false
2628
importCode?: false | ImportCodePluginOptions

‎pnpm-lock.yaml

+39-30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.