自动生成侧边栏
Docusaurus 可以根据你的文件系统结构自动生成侧边栏:每个文件夹会生成一个类别,每个文件会生成一个文档链接。
type SidebarItemAutogenerated = {
type: 'autogenerated';
dirName: string; // 生成侧边栏切片的源文件夹(相对文档目录)
};
Docusaurus 可以从你的 docs 文件夹中自动生成整个侧边栏:
export default {
myAutogeneratedSidebar: [
{
type: 'autogenerated',
dirName: '.', // '.' 即当前 docs 文件夹
},
],
};
Docusaurus将自动生成的
项转换为侧边栏切片(也在类别简写中讨论):一个由文档
或类别
类型的项目列表,因此您可以将来自多个目录的多个自动生成的
项与常规的侧边栏项交错地拼接到一个侧边栏级别中。
一个真实的例子
请考虑此文件结构:
docs
├── api
│ ├── product1-api
│ │ └── api.md
│ └── product2-api
│ ├── basic-api.md
│ └── pro-api.md
├── intro.md
└── tutorials
├── advanced
│ ├── advanced1.md
│ ├── advanced2.md
│ └── read-more
│ ├── resource1.md
│ └── resource2.md
├── easy
│ ├── easy1.md
│ └── easy2.md
├── tutorial-end.md
├── tutorial-intro.md
└── tutorial-medium.md
假设每个文档的 ID 都只是它的文件名。 如果你像这么声明了自动生成侧边栏:
export default {
mySidebar: [
'intro',
{
type: 'category',
label: 'Tutorials',
items: [
'tutorial-intro',
{
type: 'autogenerated',
dirName: 'tutorials/easy', // 从 docs/tutorials/easy 生成侧边栏切片
},
'tutorial-medium',
{
type: 'autogenerated',
dirName: 'tutorials/advanced', // 从 docs/tutorials/advanced 生成侧边栏切片
},
'tutorial-end',
],
},
{
type: 'autogenerated',
dirName: 'api', // 从 docs/api 生成侧边栏切片
},
{
type: 'category',
label: 'Community',
items: ['team', 'chat'],
},
],
};
解决方法是:
export default {
mySidebar: [
'intro',
{
type: 'category',
label: 'Tutorials',
items: [
'tutorial-intro',
// 在 docs/tutorials/easy 中的两个文件
'easy1',
'easy2',
'tutorial-medium',
// 在 docs/tutorials/advanced 中的两个文件和一个文件夹
'advanced1',
'advanced2',
{
type: 'category',
label: 'read-more',
items: ['resource1', 'resource2'],
},
'tutorial-end',
],
},
// 在 docs/api 中的两个文件夹
{
type: 'category',
label: 'product1-api',
items: ['api'],
},
{
type: 'category',
label: 'product2-api',
items: ['basic-api', 'pro-api'],
},
{
type: 'category',
label: 'Community',
items: ['team', 'chat'],
},
],
};
请注意,自动生成的源目录本身不会成为分类:只有它们包含的项才会成为分类。 这就是我们所说的“侧边栏切片”。
类别索引惯例
Docusaurus 可以自动给一个类别关联一篇索引文档。
类别索引文档的文件名符合下列条件之一:
- 名为
index
(大小写不敏感):docs/Guides/index.md
- 名为
README
(大小写不敏感):docs/Guides/README.mdx
- 和上一级目录的名字一致:
docs/Guides/Guides.md
这等价于一个使用了doc 链接的类别:
export default {
docs: [
{
type: 'category',
label: 'Guides',
link: {type: 'doc', id: 'Guides/index'},
items: [],
},
],
};
把引言文档命名为 README.md
,可以在 GitHub 上浏览此目录的时候显示这篇文档;用 index.md
则会更加接近服务器发送 HTML 文件的行为。
如果一个文件夹只有一个索引页,它会变成一个链接,而不是一个类别。 这对于把资源和文档并置很有用:
some-doc
├── index.md
├── img1.png
└── img2.png
自定义类别索引匹配
你可以选择不使用三种类别索引惯例中的任何一种,或者也可以定义更多的惯例。 你可以通过 sidebarItemsGenerator
回调注入你自己的 isCategoryIndex
匹配函数。 比如,你可以选择 intro
文件名,让它也可能自动变成类别索引。
export default {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
async sidebarItemsGenerator({
...args,
isCategoryIndex: defaultCategoryIndexMatcher, // 默认匹配函数实现,见下文
defaultSidebarItemsGenerator,
}) {
return defaultSidebarItemsGenerator({
...args,
isCategoryIndex(doc) {
return (
// 除了默认的文件名,也识别 intro.md
doc.fileName.toLowerCase() === 'intro' ||
defaultCategoryIndexMatcher(doc)
);
},
});
},
},
],
],
};
也可以选择不接受任何类别索引惯例。
export default {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
async sidebarItemsGenerator({
...args,
isCategoryIndex: defaultCategoryIndexMatcher, // 默认匹配函数实现,见下文
defaultSidebarItemsGenerator,
}) {
return defaultSidebarItemsGenerator({
...args,
isCategoryIndex() {
// 没有文档会被自动选为分类引索
return false;
},
});
},
},
],
],
};
isCategoryIndex
匹配函数会接受一个有三个属性的对象:
fileName
,不带扩展名的文件名,区分大小写directories
,一列_从最底层到最高层_的文件夹名,相对于文档根目录extension
,文件的扩展名,开头有一个点。
比如,对于一篇位于 guides/sidebar/autogenerated.md
的文档,匹配函数收到的参数会是:
const props = {
fileName: 'autogenerated',
directories: ['sidebar', 'guides'],
extension: '.md',
};
默认的匹配函数的实现是:
function isCategoryIndex({fileName, directories}) {
const eligibleDocIndexNames = [
'index',
'readme',
directories[0].toLowerCase(),
];
return eligibleDocIndexNames.includes(fileName.toLowerCase());
}
自动生成侧边栏元数据
对于手写的侧边栏定义,你会通过 sidebars.js
给每个项目提供元数据;对于自动生成的侧边栏,Docusaurus 会从项目对应的文件中读取。 除此之外,你还可能想要调整每个项目之间的相对位置,因为默认情况下,同一个侧边栏切片里的项目会根据文件和文件夹名字,按字母表顺序生成。
文档项目元数据
label
、className
、customProps
属性在前言中声明,对应的字段分别是 sidebar_label
、sidebar_class_name
、sidebar_custom_props
。 相对位置可以用一样的方法声明,也就是 sidebar_position
前言。
---
sidebar_position: 2
sidebar_label: 简单
sidebar_class_name: green
---
# 简单教程
这里是简单教程!
类别元数据
在类别相对应的文件夹里新建一个 _category_.json
或 _category_.yml
文件。 你可以声明类别所需要的任何元数据,以及 position
元数据。 如果类别有文档索引链接,label
、className
、position
、customProps
会默认为此文档的对应元数据值。
- JSON
- YAML
{
"position": 2.5,
"label": "教程",
"collapsible": true,
"collapsed": false,
"className": "red",
"link": {
"type": "generated-index",
"title": "教程总览"
},
"customProps": {
"description": "这个描述可以用在 swizzle 的 DocCard 里"
}
}
position: 2.5 # 支持浮点数序号
label: '教程'
collapsible: true # 让类别可折叠
collapsed: false # 让类别默认开启
className: red
link:
type: generated-index
title: 教程总览
customProps:
description: 这个描述可以用在 swizzle 的 DocCard 里
如果显式指定了一个 link
,Docusaurus 就不会应用任何默认惯例。
文档链接可以是相对的。比如,如果用 guides
目录生成类别,"link": {"type": "doc", "id": "intro"}
会被解析到 guides/intro
这个 ID,只有当前一个 ID 对应的文档不存在时,才会回退到 intro
ID。
你也可以用 link: null
来防止 Docusaurus 应用任何惯例,从而让类别不带有索引页。
位置元数据只会在一个侧边栏切片的内部使用:Docusaurus 不会重新排列你的侧边栏的其他项目。
使用数字前缀
有一种简单的给自动生成侧边栏排序的方法,就是给每个文档和文件夹添加一个数字前缀。这会让它们在文件系统按文件名排序时也是有序的:
docs
├── 01-Intro.md
├── 02-Tutorial Easy
│ ├── 01-First Part.md
│ ├── 02-Second Part.md
│ └── 03-End.md
├── 03-Tutorial Advanced
│ ├── 01-First Part.md
│ ├── 02-Second Part.md
│ ├── 03-Third Part.md
│ └── 04-End.md
└── 04-End.md
为了更方便使用此功能,Docusaurus 支持多种数字前缀模式。
默认情况下,Docusaurus 会从文档 ID、标签及 URL 路径中移除数字前缀。
我们推荐你使用额外的元数据。
更新数字前缀很麻烦,因为可能需要更新多个已有的 Markdown 链接:
- 查看[教程结语](../04-End.mdx);
+ 查看[教程结语](../05-End.mdx);
自定义侧边栏项生成器
你可以在文档插件(或预设)中提供自定义的 sidebarItemsGenerator
函数:
export default {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
async sidebarItemsGenerator({
defaultSidebarItemsGenerator,
numberPrefixParser,
item,
version,
docs,
categoriesMetadata,
isCategoryIndex,
}) {
// 示例:返回一列硬编码的静态侧边栏项目
return [
{type: 'doc', id: 'doc1'},
{type: 'doc', id: 'doc2'},
];
},
},
],
],
};
重复利用并增强默认的生成器,而不是从零开始写一个生成器:我们提供的默认生成器有 250 行代码长。
根据你的需要,添加、更新、筛选、重新排序现有的侧边栏项:
// 反转侧边栏项的顺序(包括嵌套的分类项)
function reverseSidebarItems(items) {
// 反转分类的子项目
const result = items.map((item) => {
if (item.type === 'category') {
return {...item, items: reverseSidebarItems(item.items)};
}
return item;
});
// 反转当前层级的项目
result.reverse();
return result;
}
export default {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
async sidebarItemsGenerator({defaultSidebarItemsGenerator, ...args}) {
const sidebarItems = await defaultSidebarItemsGenerator(args);
return reverseSidebarItems(sidebarItems);
},
},
],
],
};