close

自动生成导航 updated

在 Rspress 中,除了在配置文件中通过 themeConfig 声明 navsidebar,你也可以通过声明 _nav.json_meta.json 描述文件来自动生成导航栏和侧边栏。我们更推荐后者,它能让配置文件更简洁,支持 HMR,同时仍包含 themeConfig 下的全部能力。

提示

当配置文件 rspress.config.ts 中没有 navsidebar 配置的情况下,自动化导航栏/侧边栏才会生效。

基本用法

Rspress 通过 _nav.json 生成导航栏,通过 _meta.json 生成侧边栏。导航级别的 _nav.json 位于文档根目录中,而侧边栏级别的 _meta.json 位于文档根目录的子目录中。比如:

docs
_nav.json// 导航栏级别
guide
_meta.json// 侧边栏级别
introduction.mdx
advanced
_meta.json// 侧边栏级别
plugin-development.md

如果你的文档使用了国际化,那么导航栏级别的 _nav.json 会放置在对应语言目录下,比如:

docs
en
_nav.json// 导航栏级别
guide
_meta.json// 侧边栏级别
introduction.mdx
install.mdx
advanced
_meta.json// 侧边栏级别
plugin-development.md
zh
_nav.json// 导航栏级别
guide
_meta.json// 侧边栏级别
introduction.mdx
install.mdx
advanced
_meta.json// 侧边栏级别
plugin-development.md

全局侧边栏用法

默认情况下(根目录仅存在 _nav.json),Rspress 会为每个子目录生成独立的侧边栏,侧边栏会根据当前激活的导航项自动切换。例如,点击「Guide」导航项会显示 Guide 的侧边栏,点击「API」则显示 API 的侧边栏:

docs
_nav.json
guide
_meta.json// /guide 的侧边栏
...
api
_meta.json// /api 的侧边栏
...

如果你希望所有页面共用一个全局侧边栏,而不是按导航项切换,可以在文档根目录下添加一个 _meta.json(与 _nav.json 同级):

docs
_nav.json
_meta.json// 根目录 _meta.json → 全局侧边栏
guide
_meta.json
...
api
_meta.json
...

当根目录存在 _meta.json 时,Rspress 会生成一个以 '/' 为键的全局侧边栏,无论当前激活的是哪个导航项,侧边栏内容都保持一致。根目录的 _meta.json 作为整个侧边栏树的入口,通常引用各个子目录:

docs/_meta.json
[
  {
    "type": "dir",
    "name": "guide",
    "label": "Guide"
  },
  {
    "type": "dir",
    "name": "api",
    "label": "API"
  }
]

JSON schema 类型提示

为了更好地编辑 _nav.json_meta.json 文件,Rspress 提供了 @rspress/core/meta-json-schema.json@rspress/core/nav-json-schema.json 两个 schema 文件用于 IDE 的类型提示。

以 VSCode 为例,可以在 .vscode/settings.json 中添加如下配置:

.vscode/settings.json
{
  //...
  "json.schemas": [
    {
      "fileMatch": ["**/_meta.json"],
      "url": "./node_modules/@rspress/core/meta-json-schema.json"
      // 或者 "url": "https://unpkg.com/@rspress/[email protected]/meta-json-schema.json"
    },
    {
      "fileMatch": ["**/_nav.json"],
      "url": "./node_modules/@rspress/core/nav-json-schema.json"
      // 或者 "url": "https://unpkg.com/@rspress/[email protected]/nav-json-schema.json"
    }
  ]
  // ...
}

导航栏级别配置

在导航栏级别的情况中,你可以在 _nav.json 中填入一个数组,其类型跟默认主题的 nav 配置完全一致,详情可以参考 nav 配置。比如:

docs/_nav.json
[
  {
    "text": "Guide",
    "link": "/guide/introduction",
    "activeMatch": "^/guide/"
  }
]

侧边栏级别配置

在侧边栏级别的情况中,你可以在 _meta.json 中填入一个数组,数组每一项的类型如下:

export type FileSideMeta = {
  type: 'file';
  name: string;
  label?: string;
  tag?: string;
  overviewHeaders?: number[];
  context?: string;
};

export type DirSideMeta = {
  type: 'dir';
  name: string;
  label?: string;
  collapsible?: boolean;
  collapsed?: boolean;
  tag?: string;
  overviewHeaders?: number[];
  context?: string;
};

export type DirSectionHeaderSideMeta = Omit<DirSideMeta, 'type'> &
  Omit<SectionHeaderMeta, 'type'> & { type: 'dir-section-header' };

export type DividerSideMeta = {
  type: 'divider';
  dashed?: boolean;
};

export type SectionHeaderMeta = {
  type: 'section-header';
  label: string;
  tag?: string;
};

export type CustomLinkMeta =
  | {
      // file link
      type: 'custom-link';
      label: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
      link: string;
    }
  | {
      // dir link
      type: 'custom-link';
      label: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
      link?: string;
      collapsible?: boolean;
      collapsed?: boolean;
      items: _CustomLinkMetaWithoutTypeField[];
    };

export type SideMetaItem =
  | FileSideMeta
  | DirSideMeta
  | DirSectionHeaderSideMeta
  | DividerSideMeta
  | SectionHeaderMeta
  | CustomLinkMeta
  | string;

file

  • 当类型为 string 时,表示该项是一个文件,文件名为该字符串,比如:
["introduction"]

其中文件名可以带后缀,也可以不带后缀,比如 introduction 会被解析为 introduction.mdx

  • 当类型为对象形式时,你可以描述为一个文件、目录或者自定义链接。

在描述文件的情况下,类型如下:

export type FileSideMeta = {
  type: 'file';
  name: string;
  label?: string;
  tag?: string;
  overviewHeaders?: number[];
  context?: string;
};

其中,name 表示文件名,同时支持/不带后缀,label 表示该文件在侧边栏中的显示名称,为可选值,如果未填则会自动取文档中的 h1 标题。overviewHeaders 表示该文件在 Overview 页中展示的标题级别,为可选值,默认为 [2]context 表示在生成侧边栏时在所在的 DOM 节点添加 data-context 属性的值。为可选值,默认不会添加。比如:

{
  "type": "file",
  "name": "introduction",
  "label": "Introduction"
}

dir

在描述目录的情况下,类型如下:

export type DirSideMeta = {
  type: 'dir';
  name: string;
  label?: string;
  collapsible?: boolean;
  collapsed?: boolean;
  tag?: string;
  overviewHeaders?: number[];
  context?: string;
};

其中,name 表示目录名,label 表示该目录在侧边栏中的显示名称,collapsible 表示该目录是否可以折叠,collapsed 表示该目录是否默认折叠,overviewHeaders 表示该目录下的文件在 Overview 页中展示的标题级别,为可选值,默认为 [2],即 h2。context 表示在生成侧边栏时在所在的 DOM 节点添加 data-context 属性的值。为可选值,默认不会添加。比如:

{
  "type": "dir",
  "name": "advanced",
  "label": "Advanced",
  "collapsible": true,
  "collapsed": false
}
提示

如果想要点击侧边栏目录显示某篇文档,推荐在目录内创建 index.mdx 文件,比如:

docs
basic
guide
index.mdx
getting-started.mdx
_meta.json
_meta.json
basic/_meta.json
[{ "type": "dir", "name": "guide" }]
basic/guide/_meta.json
["getting-started"]

意为侧边栏里仅含有 getting-started 这一篇文档,当你点击 Guide 目录时,会显示 index.mdx 文件的内容。

dir-section-header new

当描述目录时,你也可以使用 dir-section-header,它与 "type": "dir" 仅在 UI 上有所变化,常用于第一级别,目录标题会以 分组标题 的形式展示,并与目录下的文件处于同一层级。

类型为:

export type DirSectionHeaderSideMeta = Omit<DirSideMeta, 'type'> &
  Omit<SectionHeaderMeta, 'type'> & { type: 'dir-section-header' };
{
  "type": "dir-section-header",
  "name": "advanced",
  "label": "Advanced",
  "collapsible": true,
  "collapsed": false
}

divider

在描述分割线的情况下,类型如下:

export type DividerSideMeta = {
  type: 'divider';
  dashed?: boolean;
};

dashedtrue 时表示该分割线是虚线,否则是实线。

section-header

在描述分组标题的情况下,类型如下:

export type SectionHeaderMeta = {
  type: 'section-header';
  label: string;
  tag?: string;
};

其中,label 表示该分组标题在侧边栏中的显示名称,比如:

{
  "type": "section-header",
  "label": "Section Header"
}

这样,你可以在侧边栏中添加分组标题,方便对文档和目录进行分组。一般情况下,你可以配合 divider 使用,来更好的区分不同的分组。比如:

[
  {
    "type": "section-header",
    "label": "Section 1"
  },
  "introduction",
  {
    "type": "divider"
  },
  {
    "type": "section-header",
    "label": "Section 2"
  },
  "advanced"
]

在描述自定义链接的情况下,类型如下:

export type CustomLinkMeta =
  | {
      // file link
      type: 'custom-link';
      label: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
      link: string;
    }
  | {
      // dir link
      type: 'custom-link';
      label: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
      link?: string;
      collapsible?: boolean;
      collapsed?: boolean;
      items: _CustomLinkMetaWithoutTypeField[];
    };

其中,label 表示该链接在侧边栏中的显示名称,link 表示该链接的跳转地址,比如:

{
  "type": "custom-link",
  "label": "My Link",
  "link": "/my-link"
}

link 支持外部链接,比如:

{
  "type": "custom-link",
  "link": "https://github.com",
  "label": "GitHub"
}

同时 custom-link 也支持嵌套链接,比如:

{
  "type": "custom-link",
  "label": "My Link",
  "items": [
    {
      "type": "custom-link",
      "label": "Sub Link 1",
      "link": "/sub-link-1"
    },
    {
      "type": "custom-link",
      "label": "Sub Link 2",
      "link": "/sub-link-2"
    }
  ]
}

完整示例

下面是一个完整的示例,用到了上述的三种类型:

[
  "install",
  {
    "type": "file",
    "name": "introduction",
    "label": "Introduction"
  },
  {
    "type": "dir",
    "name": "advanced",
    "label": "Advanced",
    "collapsible": true,
    "collapsed": false
  },
  {
    "type": "custom-link",
    "label": "My Link",
    "link": "/my-link"
  }
]

无配置用法

某些目录下你可以不配置 _meta.json,让 Rspress 自动帮你生成侧边栏。这需要保证目录下仅包含文档,而不包含子目录,并且你对文档的顺序没有要求。比如现在有如下的文档结构:

docs
_meta.json
guide
_meta.json
basic
introduction.mdx
install.mdx
plugin-development.md

guide 目录中你可以配置 _meta.json 内容如下:

[
  {
    "type": "dir",
    "name": "basic",
    "label": "Basic",
    "collapsible": true,
    "collapsed": false
  }
]

而在 basic 目录中,你可以不配置 _meta.json,Rspress 会自动帮你生成侧边栏,默认按照文件名的字母顺序排序。如果你想要自定义顺序,可以在文件名前加上数字前缀,比如:

basic
1-introduction.mdx
2-install.mdx
3-plugin-development.md

侧边栏和导航栏的 tag 图标

你可以通过 tag 配置在侧边栏或导航栏的标题后添加图标。tag 的值支持 SVG 标签字符串或图片 URL。

_meta.json
{
  "type": "file",
  "name": "introduction",
  "label": "Introduction",
  "tag": "<svg width=\"1em\" height=\"1em\" viewBox=\"0 0 32 32\"><path fill=\"currentColor\" d=\"M4 6h24v2H4zm0 18h24v2H4zm0-12h24v2H4zm0 6h24v2H4z\"/></svg>"
}

详细用法请参考 Tag 组件