Skip to content

Commit c876d6f

Browse files
committed
feat: 🚀 vitepress-plugin-auto-frontmatter 新增使用文档,优化其他插件文件
1 parent 6faddeb commit c876d6f

File tree

7 files changed

+329
-9
lines changed

7 files changed

+329
-9
lines changed

demo/docs-test/.vitepress/config.mts

+6
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ const tkConfig = tkThemeConfig({
118118
// site: "",
119119
},
120120
},
121+
vitePlugins: {
122+
autoFrontmatter: true,
123+
autoFrontmatterOption: {
124+
exclude: { a: true },
125+
},
126+
},
121127
});
122128

123129
// https://vitepress.dev/reference/site-config

demo/docs-test/02.MD 插件测试.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ sticky: 1
1313
top: true
1414
---
1515

16+
1617
试试右下角的主题颜色切换
1718

1819
## TODO 列表
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
# vitepress-plugin-auto-frontmatter
2+
3+
这是一个适用于 `vitepress` 的 Vite 插件,`vitepress` 启动时,插件会给指定的 markdown 自动生成 `frontmatter`
4+
5+
## ✨ Feature
6+
7+
- 🚀 自动生成 `frontmatter`
8+
- 🚀 支持自定义新的 `frontmatter`
9+
10+
## 🕯️ Install
11+
12+
安装 `vitepress-plugin-auto-frontmatter` 插件
13+
14+
```bash
15+
# 推荐使用 pnpm
16+
pnpm i vitepress-plugin-auto-frontmatter
17+
# or yarn
18+
yarn add vitepress-plugin-auto-frontmatter
19+
# or npm
20+
npm install vitepress-plugin-auto-frontmatter
21+
```
22+
23+
添加 `vitepress-plugin-auto-frontmatter` 插件到 `.vitepress/config.ts`
24+
25+
```typescript
26+
import AutoFrontmatter from "vitepress-plugin-auto-frontmatter";
27+
28+
export default defineConfig({
29+
vite: {
30+
plugins: [AutoFrontmatter(/* options */)],
31+
},
32+
});
33+
```
34+
35+
> 说明:该插件仅限项目启动时生效。
36+
37+
插件默认忽略 `frontmatter``layout: home``["node_modules", "dist"]` 目录下的文件,且只扫描 markdown 文档。
38+
39+
插件默认给 markdown 文件生成 `title``date` 两个属性,其中 `title` 为文件名(支持带序号的文件名,如 `01.xx.md`),`date` 为文件的创建日期。
40+
41+
```yaml
42+
---
43+
title: 文件名
44+
date: yyyy-MM-dd hh:mm:ss
45+
---
46+
```
47+
48+
如果想要拓展新的 `frontmatter`,往下看 `Example 2``Example 3`
49+
50+
## 🛠️ Options
51+
52+
| name | description | type | default |
53+
| ----------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------- |
54+
| pattern | 扫描的文件路径表达式,为 global 表达式 | `string | string[]` | |
55+
| include | include 指定的对象如果不在 markdown frontmatter 存在,则忽略该文件 | `Record<string, any>` | |
56+
| exclude | exclude 指定的对象如果在 markdown frontmatter 存在,则忽略该文件。当 include 和 exclude 存在相同文件时,exclude 优先级高 | `Record<string, any>` | |
57+
| transform | 转换处理好的 frontmatter,该函数需要返回一个新的 frontmatter 或只返回 undefined,如果返回 {},则清空 MD 文件本身存在的 frontmatter | `(frontmatter: Record<string, any>, fileInfo: FileInfo) => Record<string, any> | void` | |
58+
| globOptions | tinyglobby 的配置项,*插件默认已经忽略 node_modules 和 dist 目录的所有文件 | `GlobOptions` | |
59+
60+
`globOptions``tinyglobby` 插件配置项,如果你需要忽略某些路径,可以使用该配置项 `globOptions.ignore`。更多用法请去 tinyglobby 官网查看。
61+
62+
## 📖 Usage
63+
64+
如果想拓展 `frontmatter` 的内容,则使用 `transform` 函数。
65+
66+
### Example 1
67+
68+
假设一个文件名为 `guide.md``frontmatter` 如下:
69+
70+
```yaml
71+
---
72+
tag: true
73+
---
74+
```
75+
76+
使用 `exclude` 排除该 `frontmatter` 来生成新的 `frontmatter`
77+
78+
```typescript
79+
const excludeFile = () => {
80+
const plugins: PluginOption[] = [];
81+
const autoFrontmatterOption = {
82+
pattern: "**/*.md",
83+
exclude: { tag: true }, // 排除 tag: true 的 MD 文件,支持多个配置
84+
};
85+
86+
plugins.push(AutoFrontmatter(autoFrontmatterOption));
87+
88+
return {
89+
vite: {
90+
plugins,
91+
},
92+
};
93+
};
94+
```
95+
96+
使用 `include` 只对该 `frontmatter` 生成新的 `frontmatter`
97+
98+
```typescript
99+
const excludeFile = () => {
100+
const plugins: PluginOption[] = [];
101+
const autoFrontmatterOption = {
102+
pattern: "**/*.md",
103+
include: { tag: true }, // 支持多个配置
104+
};
105+
106+
plugins.push(AutoFrontmatter(autoFrontmatterOption));
107+
108+
return {
109+
vite: {
110+
plugins,
111+
},
112+
};
113+
};
114+
```
115+
116+
最终生成如下:
117+
118+
```yaml
119+
---
120+
title: guide
121+
date: 2025-03-04
122+
---
123+
```
124+
125+
### Example 2
126+
127+
通过 `transform` 函数来添加一个唯一的永久链接:
128+
129+
```typescript
130+
const addPermalink = () => {
131+
const plugins: PluginOption[] = [];
132+
const autoFrontmatterOption = { pattern: "**/*.md" };
133+
134+
autoFrontmatterOption.transform = (frontmatter) => {
135+
// 调用可能存在的 transform(支持外界使用)
136+
let transformResult = transform?.(frontmatter, fileInfo) || {};
137+
138+
// 如果文件本身存在了 permalink,则不生成
139+
if (!frontmatter.permalink) {
140+
transformResult = { ...transformResult, ...createPermalink() };
141+
}
142+
143+
// 确保返回值存在,如果返回 {} 将会清空文件本身的 frontmatter,返回 undefined 则告诉插件不使用 transform 返回的数据
144+
return Object.keys(transformResult).length ? { ...frontmatter, ...transformResult } : undefined;
145+
};
146+
147+
plugins.push(AutoFrontmatter(autoFrontmatterOption));
148+
149+
return {
150+
vite: {
151+
plugins
152+
}
153+
}
154+
}
155+
156+
/**
157+
* 创建 permalink 永久链接
158+
*/
159+
export const createPermalink = () => {
160+
return {
161+
permalink: `/pages/${(Math.random() + Math.random()).toString(16).slice(2, 8)}`,
162+
};
163+
};
164+
```
165+
166+
效果如下:
167+
168+
```yaml
169+
---
170+
date: 2025-03-03 00:45:16
171+
title: 插件测试
172+
permalink: /pages/eb8f2f
173+
---
174+
```
175+
176+
### Example 3
177+
178+
通过 `transform` 函数来基于文件路径添加目录,如:
179+
180+
```
181+
.
182+
├─ docs # 项目根目录
183+
│ ├─ guide
184+
│ │ ├─ vue
185+
│ │ │ └─ getting.md
186+
```
187+
188+
`getting.md` 文件的 `frontmatter` 将会生成:
189+
190+
```yaml
191+
---
192+
categories:
193+
- guide
194+
- vue
195+
---
196+
```
197+
198+
需要使用 `transform` 的第二个参数,代码如下:
199+
200+
```typescript
201+
const addCategories = () => {
202+
const plugins: PluginOption[] = [];
203+
const autoFrontmatterOption = { pattern: "**/*.md" };
204+
205+
autoFrontmatterOption.transform = (frontmatter, fileInfo) => {
206+
// 调用可能存在的 transform(支持外界使用)
207+
let transformResult = transform?.(frontmatter, fileInfo) || {};
208+
209+
// 如果文件本身存在了 categories,则不生成
210+
if (!frontmatter.categories) {
211+
transformResult = { ...transformResult, ...createCategories(fileInfo) };
212+
}
213+
214+
// 确保返回值存在,如果返回 {} 将会清空文件本身的 frontmatter,返回 undefined 则告诉插件不使用 transform 返回的数据
215+
return Object.keys(transformResult).length ? { ...frontmatter, ...transformResult } : undefined;
216+
};
217+
218+
plugins.push(AutoFrontmatter(autoFrontmatterOption));
219+
220+
return {
221+
vite: {
222+
plugins
223+
}
224+
}
225+
}
226+
227+
/**
228+
* 创建 categories 分类列表
229+
*
230+
* @param fileInfo 文件信息
231+
*/
232+
export const createCategory = (fileInfo: FileInfo) => {
233+
// relativePath 为基于 vp srcDir 的相对路径,默认是基于项目根目录,如 guide/vue/getting.md
234+
const relativePathArr = fileInfo.relativePath.split("/");
235+
236+
const categories: string[] = [];
237+
relativePathArr.forEach((item, index) => {
238+
// 忽略文件名
239+
if (index !== relativePathArr.length - 1))
240+
categories.push(filename);
241+
});
242+
243+
// [""] 表示添加一个为空的 categories
244+
return { categories: categories.length ? categories : [""] };
245+
};
246+
```
247+
248+
效果如下:
249+
250+
```yaml
251+
---
252+
date: 2025-03-03 00:45:16
253+
title: getting
254+
categories:
255+
- guide
256+
- vue
257+
---
258+
```
259+
260+
> 如果 `transform` 函数返回的 `frontmatter` 已经在文件存在(只比较 Key 是否相同,不比较 Value),则忽略生成。
261+
262+
## 📘 TypeScript
263+
264+
### 🛠️ Options
265+
266+
```typescript
267+
import type { GlobOptions } from "tinyglobby";
268+
269+
export interface AutoFrontmatterOption {
270+
/**
271+
* 扫描的文件路径表达式,为 global 表达式
272+
*/
273+
pattern?: string | string[];
274+
/**
275+
* include 指定的对象如果不在 markdown frontmatter 存在,则忽略该文件
276+
*/
277+
include?: Record<string, any>;
278+
/**
279+
* exclude 指定的对象如果在 markdown frontmatter 存在,则忽略该文件。当 include 和 exclude 存在相同文件时,exclude 优先级高
280+
*/
281+
exclude?: Record<string, any>;
282+
/**
283+
* 转换处理好的 frontmatter,该函数需要返回一个新的 frontmatter 或只返回 undefined,如果返回 {},则清空 MD 文件本身存在的 frontmatter
284+
*/
285+
transform?: (frontmatter: Record<string, any>, fileInfo: FileInfo) => Record<string, any> | void;
286+
/**
287+
* tinyglobby 的配置项
288+
* 插件默认已经忽略 node_modules 和 dist 目录的所有文件
289+
*/
290+
globOptions?: GlobOptions;
291+
}
292+
293+
export interface FileInfo {
294+
/**
295+
* 文件绝对路径
296+
*/
297+
filePath: string;
298+
/**
299+
* 文件相对路径
300+
*/
301+
relativePath: string;
302+
}
303+
```
304+
305+
## License
306+
307+
[MIT](../../LICENSE) License © 2025 [Teeker](https://github.com/Kele-Bingtang)

plugins/vitepress-plugin-auto-frontmatter/src/types.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ export interface AutoFrontmatterOption {
66
*/
77
pattern?: string | string[];
88
/**
9-
* include 指定的对象如果在 markdown frontmatter 存在,则生成额外 frontmatter
9+
* include 指定的对象如果不在 markdown frontmatter 存在,则忽略该文件
1010
*/
1111
include?: Record<string, any>;
1212
/**
13-
* exclude 指定的对象如果在 markdown frontmatter 存在,则不生成额外 frontmatter,相同文件优先级高于 include
13+
* exclude 指定的对象如果在 markdown frontmatter 存在,则忽略该文件。当 include 和 exclude 存在相同文件时,exclude 优先级高
1414
*/
1515
exclude?: Record<string, any>;
1616
/**
17-
* 转换处理好的 frontmatter
17+
* 转换处理好的 frontmatter,该函数需要返回一个新的 frontmatter 或只返回 undefined,如果返回 {},则清空 MD 文件本身存在的 frontmatter
1818
*/
1919
transform?: (frontmatter: Record<string, any>, fileInfo: FileInfo) => Record<string, any> | void;
2020
/**
@@ -25,6 +25,12 @@ export interface AutoFrontmatterOption {
2525
}
2626

2727
export interface FileInfo {
28+
/**
29+
* 文件绝对路径
30+
*/
2831
filePath: string;
32+
/**
33+
* 文件相对路径
34+
*/
2935
relativePath: string;
3036
}

plugins/vitepress-plugin-catalogue/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ path 是基于 [srcDir](https://vitepress.dev/zh/reference/site-config#srcdir)
7979
"title": "vue",
8080
"children": [
8181
{ "title": "getting", "link": "/guide/vue/getting" },
82-
{ "title": "getting", "link": "/guide/vue/routing" }
82+
{ "title": "routing", "link": "/guide/vue/routing" }
8383
]
8484
},
8585
{
@@ -95,7 +95,7 @@ path 是基于 [srcDir](https://vitepress.dev/zh/reference/site-config#srcdir)
9595
"title": "vue",
9696
"children": [
9797
{ "title": "getting", "link": "/guide/vue/getting" },
98-
{ "title": "getting", "link": "/guide/vue/routing" }
98+
{ "title": "routing", "link": "/guide/vue/routing" }
9999
]
100100
},
101101
{
@@ -113,7 +113,7 @@ path 是基于 [srcDir](https://vitepress.dev/zh/reference/site-config#srcdir)
113113
"title": "vue",
114114
"children": [
115115
{ "title": "getting", "link": "/guide/vue/getting" },
116-
{ "title": "getting", "link": "/guide/vue/routing" }
116+
{ "title": "routing", "link": "/guide/vue/routing" }
117117
]
118118
},
119119
{
@@ -187,7 +187,7 @@ export interface Catalogue {
187187
[key: string]: { path: string; catalogues: CatalogueItem[] };
188188
};
189189
/**
190-
* key 为path:扫描的目录页路径文,value 为 { path:件相对路径, catalogues:目录页数据 }
190+
* key 为 path:扫描的目录页路径文,value 为 { path:件相对路径, catalogues:目录页数据 }
191191
*/
192192
inv: {
193193
[key: string]: { filePath: string; catalogues: CatalogueItem[] };

0 commit comments

Comments
 (0)