VitePress 自动生成目录插件
VitePress 是继 VuePress
后全新的静态站点生成器,基于 Vite
实现最大的特点就是快,官网对其的介绍是 Simple, powerful, and fast
,非常适合搭建博客和组件库文档等。
最近 VitePress
更新到了 v1.0.0-rc
版本,基本处于可以放心使用的状态。如果还不熟悉,可以查看官方中文文档或我的个人文档。
使用中的问题
使用 VitePress
搭建文档站点的一个问题是:当文章数量上去后,每次都需要手动配置 sidebar
目录,比较繁琐。
所以我开发了 vite-plugin-vitepress-auto-nav 插件,并发布到 npm。比如目录格式为:
- A
- a1
- a1-1.md
- a1-2.md
- a2.md
- B
- b1
- b1-1.md
- b2
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
生成的配置就是:
js
{
nav: [
{
text: 'A',
activeMatch: '/A/',
link: '/A/a1/a1-1',
},
{
text: 'B',
activeMatch: '/B/',
link: '/B/b1/b1-1',
},
],
sidebar: {
'/A/': [
{
text: 'a1',
items: [
{ text: 'a1-1', link: '/A/a1/a1-1' },
{ text: 'a1-2', link: '/A/a1/a1-2' },
],
},
{ text: 'a2', link: '/A/a2' },
],
'/B/': [
{
text: 'b1',
items: [
{ text: 'b1-1', link: '/B/b1/b1-1' },
],
},
],
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
VitePress 中有两个关键的配置选项
srcDir
:定义文档根目录,默认为项目根目录。例如在 VitePress 作为组件库文档时常将docs
作为文档目录,就可以通过 srcDir 设置srcExclude
:值为 glob 表达式,作用是排除掉匹配的文件,被排除的文件无法访问到(打包时生效)
插件应该基于这两个配置,仅读取 srcDir 内,非 scrExclude 的文件
插件功能
- 支持自定义读取范围(基于
srcDir
与srcExclude
配置) - 将一级文件夹作为
nav
,将次级文件夹和文件作为sidebar
- 支持插件配置与文章
frontmatter
配置两种自定义方式 - 支持自定义显示名称,文章还支持一级标题作为名称
- 支持自定义排序方法
- 支持自定义隐藏文件或文件夹
- 修改插件配置或
frontmatter
后自动刷新
使用方法
- 安装
sh
# 推荐使用 pnpm
pnpm i vite-plugin-vitepress-auto-nav -D
# 使用 ts 时推荐安装 vite,否则会有类型错误
pnpm i vite -D
1
2
3
4
2
3
4
- 添加插件
ts
// .vitepress/config.ts
import AutoNav from "vite-plugin-vitepress-auto-nav";
export default defineConfig({
vite: {
plugins: [
AutoNav({
// 自定义配置
}),
],
},
});
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- 正常启动项目即可使用
插件配置
在文章 frontmatter
中也可以配置 ItemOptions
中的属性。同时支持配置为 nav-属性名
的格式,可以避免与逻辑中的变量重名。对于 frontmatter
中其他的变量,也会加入到排序函数参数的 frontmatter
属性中
ts
interface Options {
/**
* glob 匹配表达式
*
* 会匹配 vitepress 配置中的 [srcDir] 目录下,除 [srcExclude] 外满足表达式的 md 文件
*
* 默认:**.md
*/
pattern?: string | string[];
/**
* 对特定文件或文件夹进行配置
*
* 键名为文件名、文件夹名或路径(以 [srcDir] 为根目录,从外层文件夹往里进行查找,md 扩展名可以省略;名称重复时,用路径区分)
*
* md 文件的配置也可以写在 frontmatter 中,使用相同 `属性名`]` 或 `nav-属性名`。优先级高于 itemsSetting 配置
*/
itemsSetting?: Record<string, ItemOptions>;
/**
* 自定义排序方法,同级文件、文件夹会调用这个函数进行排序
*
* 默认排序方法 defaultCompareFn 规则为:
*
* 1. 都有 sort 值时,先按 sort 值升序排列再按创建时间升序排列
* 2. 只有一个有 sort 值,且 sort 值等于另一个的下标值时,有 sort 值的在前
* 3. 只有一个有 sort 值,且 sort 值不等于另一个的下标值时,对比 sort 值与下标值,升序排列
* 4. 都没有 sort 值时,对比创建时间(`firstCommitTime` || `birthTime`)顺序排列
*/
compareFn?: (a: Item, b: Item) => number;
/** 是否使用文章中的一级标题代替文件名作为文章名称(处理文件名可能是简写的情况),也可以在 itemsSetting 中单独配置 */
useArticleTitle?: boolean;
}
/**
* 单个文件、文件夹配置项
*
* 也支持在文章的 frontmatter 中配置 `同名属性` 或 `nav-属性名`,优先级高于 itemsSetting 中的配置
*/
interface ItemOptions {
/** 是否显示 */
hide?: boolean;
/** 排序值(目标位置下标,从0开始) */
sort?: number;
/** 重定义展示名称,优先级高于 useArticleTitle */
title?: string;
/** 是否使用文章中的一级标题代替文件名作为文章名称,优于全局 useArticleTitle 配置 */
useArticleTitle?: boolean;
/**
* 同 sidebar 中 collapsed 配置,只对文件夹生效
*
* 默认:false(支持折叠,默认展开)
*/
collapsed?: boolean;
}
/** 文件、文件夹关键信息 */
interface Item {
/** 同级中的位置下标 */
index: number;
/** 文件、文件夹名 */
name: string;
/** 是否是文件夹 */
isFolder: boolean;
/** 配置对象(不包括frontmatter),以及时间戳数据(TimesInfo) */
options: ItemCacheOptions;
/** frontmatter 数据以及文章一级标题(h1) */
frontmatter: Frontmatter;
/** 子文件、文件夹 */
children: Item[];
}
/** 缓存的 options 数据 */
type ItemCacheOptions = ItemOptions & TimesInfo;
/** 文件、文件夹时间戳信息 */
interface TimesInfo {
/** 本地文件创建时间 */
birthTime?: number;
/** 本地文件修改时间 */
modifyTime?: number;
/** git首次提交时间 */
firstCommitTime?: number;
/** git最后一次提交时间 */
lastCommitTime?: number;
}
/** 缓存的 frontmatter 数据 */
type Frontmatter = { h1?: string } & Recordable;
type Recordable = Record<string, any>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
生成的
nav
配置,会使用目录下第一篇文章作为link
属性。如果需要自定义nav
可以直接手动定义,此时插件将不会修改已存在的nav
配置(因为nav
配置通常较少,手动配置相较于插件中进行复杂的配置性价比更高)
配置示例
ts
vite: {
plugins: [
AutoNav({
pattern: ["**/!(README|TODO).md"], // 也可以在这里排除不展示的文件,例如不匹配 README 和 TODO 文件
settings: {
a: { hide: true }, // 不显示名称为 a 的文件夹或 md 文件
b: { title: 'bb' }, // 名称为 b 的文件夹或文件在菜单中显示为 bb
c/b: { sort : 3 }, // 通过路径精确匹配 c 文件夹下的 b 进行配置,排序时位于下标3的位置或最后
c/b2: { useArticleTitle: false }, // 关闭使用文章一级标题作为文章名称
d: { collapsed: true }, // 文件夹折叠配置
},
compareFn: (a, b) => {
// 按最新提交时间(没有提交记录时为本地文件修改时间)升序排列
return (b.options.lastCommitTime || b.options.modifyTime) - (a.options.lastCommitTime || a.options.modifyTime)
},
useArticleTitle: true // 全局开启使用文章一级标题作为文章名称
}),
],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19