VitePress

982 阅读10分钟

image.png

介绍

VitePress 是一个静态站点生成器 (SSG),专为构建快速、以内容为中心的站点而设计。

核心架构

VitePress 的架构精妙地融合了几个关键技术:

  • Vite:作为现代前端开发和构建工具,Vite 提供了极快的服务器启动和热模块替换(HMR)。
  • Vue.js:用于创建互动式 UI 和前端动态内容。Vue 的组件系统允许你以模块化的方式构建页面。
  • Markdown:所有的内容都是用 Markdown 编写的,这使得内容创作变得简单而直观。Markdown 文件可以轻松转换成 HTML,同时支持 Vue 组件,让你可以在文档中嵌入动态内容。

主要特点

  • 速度与效率:VitePress 的最大卖点之一是其出色的性能。使用 Vite 作为底层工具,它实现了极快的页面加载和热更新,大大提高了开发效率。
  • SEO 友好:虽然是一个单页面应用(SPA)生成器,但 VitePress 生成的页面是 SEO 友好的。它在构建时生成静态 HTML,确保了内容的可索引性。
  • 静态资源处理:VitePress 提供了先进的静态资源处理能力,包括图片、样式表和 JavaScript 文件的优化。这意味着你可以轻松管理和部署资源,确保网站的快速加载。
  • 易于定制和扩展:VitePress 的架构设计允许你轻松定制主题和扩展功能。你可以使用 Vue 组件和 Vite 插件来增强你的站点,无论是添加自定义功能还是改进用户界面。

安装

前置准备

安装并初始化

  npm i vitepress
  
  $ npx vitepress init
  将需要回答几个简单的问题:
  
  ┌  Welcome to VitePress!
 │
 ◇  Where should VitePress initialize the config? //VitePress 应该在哪里初始化配置
 │  ./docs
 │
 ◇  Site title: //标题
 │  My Awesome Project
 │
 ◇  Site description: //描述
 │  A VitePress Site
 │
 ◆  Theme: //主题
 │  ● Default Theme (Out of the box, good-looking docs)
 │  ○ Default Theme + Customization
 │  ○ Custom Theme
 └

文档结构

.  
├─ docs  
│  ├─ .vitepress  
│  │  └─ config.js  
│  ├─ api-examples.md  
│  ├─ markdown-examples.md  
│  └─ index.md  
└─ package.json

路由

根目录和源目录

根目录

项目根目录是 VitePress 将尝试寻找 .vitepress 特殊目录的地方。.vitepress 目录是 VitePress 配置文件、开发服务器缓存、构建输出和可选主题自定义代码的预留位置。

当从命令行运行 vitepress dev 或 vitepress build 时,VitePress 将使用当前工作目录作为项目根目录。要将子目录指定为根目录,需要将相对路径传递给命令。例如,如果 VitePress 项目位于 ./docs,应该运行 vitepress dev docs

.
├─ docs                    # 项目根目录
│  ├─ .vitepress           # 配置目录
│  ├─ getting-started.md
│  └─ index.md
└─ ...
vitepress dev docs

这将导致以下源代码到 HTML 的映射:

docs/index.md            -->  /index.html (可以通过 / 访问)
docs/getting-started.md  -->  /getting-started.html

这通常用于项目中集成一个vitepress 文档

源目录

源目录是 Markdown 源文件所在的位置。默认情况下,它与项目根目录相同。但是,可以通过 srcDir 配置选项对其进行配置。

srcDir 选项是相对于项目根目录解析的。例如,对于 srcDir: 'src',文件结构将如下所示:

.                          # 项目根目录
├─ .vitepress              # 配置目录
└─ src                     # 源目录
   ├─ getting-started.md
   └─ index.md

生成的源代码到 HTML 的映射:

src/index.md            -->  /index.html (可以通过 / 访问)
src/getting-started.md  -->  /getting-started.html

链接页面

在页面之间链接时,可以使用绝对路径和相对路径。请注意,虽然 .md 和 .html 扩展名都可以使用,但最佳做法是省略文件扩展名,以便 VitePress 可以根据配置生成最终的 URL。

[显示内容](./路径) 

链接到非 VitePress 页面

如果想链接到站点中不是由 VitePress 生成的页面,需要使用完整的 URL(在新选项卡中打开)或明确指定 target:

[Link to pure.html](/pure.html){target="_self"}

生成简洁的 URL

某些服务器或托管平台 (例如 Netlify、Vercel 或 GitHub Pages) 提供将 /foo 之类的 URL 映射到 /foo.html (如果存在) 的功能,而无需重定向:

如果可以使用此功能,还可以启用 VitePress 自己的 cleanUrls 配置选项,以便:

  • 页面之间的入站链接是在没有 .html 扩展名的情况下生成的。
  • 如果当前路径以 .html 结尾,路由器将执行客户端重定向到无扩展路径。

路由重写

可以自定义源目录结构和生成页面之间的映射。当有一个复杂的项目结构时,它很有用。例如,假设有一个包含多个包的 monorepo,并且希望将文档与源文件一起放置,如下所示:

export default {
  rewrites: {
    'packages/pkg-a/src/pkg-a-docs.md': 'pkg-a/index.md',
    'packages/pkg-b/src/pkg-b-docs.md': 'pkg-b/index.md',
    'packages/:pkg/src/(.*)': ':pkg/index.md'
  }
}

重写路径是使用 path-to-regexp 包编译的——请参阅其文档以获取更多语法。

例如


  themeConfig: {
    // https://vitepress.dev/reference/default-theme-config
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Examples', link: '/markdown-examples' }
    ],
    sidebar: [
      {
        text: 'Examples',
        items: [
          { text: 'Markdown Examples', link: '/markdown-examples' },
          { text: 'Runtime API Examples', link: '/api-examples' },
          { text: 'Runtime API Examples', link: '/dex.md' },
        ]
      },
    ],
    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
    ]
  },
  rewrites: {
    'docs/aaa/i.md': 'dex.md'
  },

// 其实就是让路由看起来一致

路由参数

比如区分不同版本的文档(没看懂官网暂时省略)

部署

本地构建与测试

  1. 可以运行以下命令来构建文档:
$ npm run docs:build
  1. 构建文档后,通过运行以下命令可以在本地预览它:

    $ npm run docs:preview
    

    preview 命令将启动一个本地静态 Web 服务 http://localhost:4173,该服务以 .vitepress/dist 作为源文件。这是检查生产版本在本地环境中是否正常的一种简单方法。

  2. 可以通过传递 --port 作为参数来配置服务器的端口。

    {
      "scripts": {
        "docs:preview": "vitepress preview docs --port 8080"
      }
    }
    

现在 docs:preview 方法将会在 http://localhost:8080 启动服务。

设置public 根目录

// 服务器访问前缀

    export default defineConfig({
        title: 'Robinson',
        description: 'Documentations of @taiyuuki/utils',
        base: '/Robinson/', //public根目录
        outDir: "./docsDist",
        lastUpdated: true,
    })

githubPage部署

在项目的 .github/workflows 目录中创建一个名为 deploy.yml 的文件,其中包含这样的内容:

# 构建 VitePress 站点并将其部署到 GitHub Pages 的示例工作流程
#
name: Deploy VitePress site to Pages

on:
  # 在针对 `main` 分支的推送上运行。如果你
  # 使用 `master` 分支作为默认分支,请将其更改为 `master`
  push:
    branches: [main]

  # 允许你从 Actions 选项卡手动运行此工作流程
  workflow_dispatch:

# 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# 只允许同时进行一次部署,跳过正在运行和最新队列之间的运行队列
# 但是,不要取消正在进行的运行,因为我们希望允许这些生产部署完成
concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  # 构建工作
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 如果未启用 lastUpdated,则不需要
      # - uses: pnpm/action-setup@v3 # 如果使用 pnpm,请取消此区域注释
      #   with:
      #     version: 9
      # - uses: oven-sh/setup-bun@v1 # 如果使用 Bun,请取消注释
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm # 或 pnpm / yarn
      - name: Setup Pages
        uses: actions/configure-pages@v4
      - name: Install dependencies
        run: npm ci # 或 pnpm install / yarn install / bun install
      - name: Build with VitePress
        run: npm run docs:build # 或 pnpm docs:build / yarn docs:build / bun run docs:build
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/.vitepress/dist

  # 部署工作
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
  1. 在存储库设置中的“Pages”菜单项下,选择“Build and deployment > Source > GitHub Actions”。
  2. 将更改推送到 main 分支并等待 GitHub Action 工作流完成。你应该看到站点部署到 https://<username>.github.io/[repository]/ 或 https://<custom-domain>/,这取决于你的设置。你的站点将在每次推送到 main 分支时自动部署。

Markdown语法与扩展

markdown

标题

Markdown语法HTML预览效果
# Heading level 1<h1>Heading level 1</h1># Heading level 1
## Heading level 2<h2>Heading level 2</h2>## Heading level 2
### Heading level 3<h3>Heading level 3</h3>### Heading level 3
#### Heading level 4<h4>Heading level 4</h4>#### Heading level 4
##### Heading level 5<h5>Heading level 5</h5>##### Heading level 5
###### Heading level 6<h6>Heading level 6</h6>###### Heading level 6

换行

在一行的末尾添加两个或多个空格,然后按回车键,即可创建一个换行(<br>)。

强调语法

粗体
Markdown语法HTML预览效果
I just love **bold text**.I just love <strong>bold text</strong>.I just love bold text.
I just love __bold text__.I just love <strong>bold text</strong>.I just love bold text.
Love**is**boldLove<strong>is</strong>boldLoveisbold
斜体
Markdown语法HTML预览效果
Italicized text is the *cat's meow*.Italicized text is the <em>cat's meow</em>.Italicized text is the cat’s meow.
Italicized text is the _cat's meow_.Italicized text is the <em>cat's meow</em>.Italicized text is the cat’s meow.
A*cat*meowA<em>cat</em>meowAcatmeow

引用语法

 > 这是一段引用

这是一段引用

列表语法

有序列表
Markdown语法HTML预览效果
1. First item 2. Second item 3. Third item 4. Fourth item<ol> <li>First item</li> <li>Second item</li> <li>Third item</li> <li>Fourth item</li> </ol>1. First item
2. Second item
3. Third item
4. Fourth item`
无序列表
Markdown语法HTML
- First item - Second item - Third item - Fourth item<ul> <li>First item</li> <li>Second item</li> <li>Third item</li> <li>Fourth item</li> </ul>
  • First item
  • Second item
  • Third item
  • Fourth item

注意 有序无序列表可以相互之间嵌套

代码语法

Markdown语法HTML预览效果
``Use `code` in your Markdown file.``<code>Use `code` in your Markdown file.</code>Use `code` in your Markdown file.

分隔线

--- 或***


链接语法

[文字](url)

link

图片语法

[![沙漠中的岩石图片](/assets/img/shiprock.jpg "Shiprock")](https://markdown.com.cn)

其他

如 html 标签

扩展

frontmatter语法

任何包含 YAML front matter 块的文件都将是 由 Jekyll 作为特殊文件处理。前言必须是第一件事 ,并且必须采用在三短划线 线。下面是一个基本示例

--- 
layout: post title: 
Blogging Like a Hacker 
---

可以通过 Vue 表达式中的 $frontmatter 全局变量访问 frontmatter 数据:

{{ $frontmatter.title }}
title
  • 类型:string

页面的标题。它与 config.title 相同,并且覆盖站点级配置。

yaml

---
title: VitePress
---
titleTemplate
  • 类型:string | boolean

标题的后缀。它与 config.titleTemplate 相同,它会覆盖站点级别的配置。

---
title: VitePress
titleTemplate: Vite & Vue powered static site generator
---
description
  • 类型:string

页面的描述。它与 config.description 相同,它会覆盖站点级别的配置。

---
description: VitePress
---
head
  • 类型:HeadConfig[]

指定要为当前页面注入的额外 head 标签。将附加在站点级配置注入的头部标签之后。

---
head:
  - - meta
    - name: description
      content: hello
  - - meta
    - name: keywords
      content: super duper SEO
---
type HeadConfig =
  | [string, Record<string, string>]
  | [string, Record<string, string>, string]
仅默认主题

以下 frontmatter 选项仅在使用默认主题时适用。

layout
  • 类型:doc | home | page
  • 默认值:doc

指定页面的布局。

  • doc——它将默认文档样式应用于 markdown 内容。
  • home——“主页”的特殊布局。可以添加额外的选项,例如 hero 和 features,以快速创建漂亮的落地页。
  • page——表现类似于 doc,但它不对内容应用任何样式。当想创建一个完全自定义的页面时很有用。

yaml

---
layout: doc
---
hero home page only

当 layout 设置为 home 时,定义主页 hero 部分的内容。更多详细信息:默认主题:主页

features home page only

定义当layout 设置为 home 时要在 features 部分中显示的项目。更多详细信息:默认主题:主页

navbar
  • 类型:boolean
  • 默认值:true

是否显示导航栏

yaml

---
navbar: false
---
sidebar
  • 类型:boolean
  • 默认值:true

是否显示 侧边栏.

yaml

---
sidebar: false
---
aside
  • 类型:boolean | 'left'
  • 默认值:true

定义侧边栏组件在 doc 布局中的位置。

将此值设置为 false 可禁用侧边栏容器。
将此值设置为 true 会将侧边栏渲染到右侧。
将此值设置为 left 会将侧边栏渲染到左侧。

yaml

---
aside: false
---
outline
  • 类型:number | [number, number] | 'deep' | false
  • 默认值:2

大纲中显示的标题级别。它与 config.themeConfig.outline.level 相同,它会覆盖站点级的配置。

lastUpdated
  • 类型:boolean | Date
  • 默认值:true

是否在当前页面的页脚中显示最后更新时间的文本。如果指定了日期时间,则会显示该日期时间而不是上次 git 修改的时间戳。

---
lastUpdated: false
---
editLink
  • 类型:boolean
  • 默认值:true

是否在当前页的页脚显示编辑链接

---
editLink: false
---
footer
  • 类型:boolean
  • 默认值:true

是否显示页脚

---
footer: false
---
pageClass
  • 类型:string

将额外的类名称添加到特定页面。

---
pageClass: custom-page-class
---

然后可以在 .vitepress/theme/custom.css 文件中自定义该特定页面的样式:

.custom-page-class {
  /* 特定页面的样式 */
}

VitePress 也支持 JSON 格式的 frontmatter,以花括号开始和结束:

json

---
{
  "title": "Blogging Like a Hacker",
  "editLink": true
}
---

GitHub 风格的表格

输入

| Tables        |      Are      |  Cool |
| ------------- | :-----------: | ----: |
| col 3 is      | right-aligned | $1600 |
| col 2 is      |   centered    |   $12 |
| zebra stripes |   are neat    |    $1 |

输出

TablesAreCool
col 3 isright-aligned$1600
col 2 iscentered$12
zebra stripesare neat$1

Emoji

:tada: :100:

🎉 💯 emoji列表

目录

[[toc]] 可以使用 markdown.toc 选项配置 TOC 的呈现效果。

自定义容器

::: info
This is an info box.
:::

::: tip
This is a tip.
:::

::: warning
This is a warning.
:::

::: danger
This is a dangerous warning.
:::

::: details
This is a details block.
:::

此外,可以通过在站点配置中添加以下内容来全局设置自定义标题,如果不是用英语书写,这会很有帮助:

// config.ts
export default defineConfig({
  // ...
  markdown: {
    container: {
      tipLabel: '提示',
      warningLabel: '警告',
      dangerLabel: '危险',
      infoLabel: '信息',
      detailsLabel: '详细信息'
    }
  }
  // ...
})

raw

这是一个特殊的容器,可以用来防止与 VitePress 的样式和路由冲突。这在记录组件库时特别有用。可能还想查看 whyframe 以获得更好的隔离。

::: raw
Wraps in a <div class="vp-raw">
:::

GitHub 风格的警报

> [!NOTE]
> 强调用户在快速浏览文档时也不应忽略的重要信息。

> [!TIP]
> 有助于用户更顺利达成目标的建议性信息。

> [!IMPORTANT]
> 对用户达成目标至关重要的信息。

> [!WARNING]
> 因为可能存在风险,所以需要用户立即关注的关键内容。

> [!CAUTION]
> 行为可能带来的负面影响。

代码高亮

这里可以配置 高亮主题在主题会详细说

//这里第四行会高亮

export default {
  data () {
    return {
      msg: 'Highlighted!'
    }
  }
}

除了单行之外,还可以指定多个单行、多行,或两者均指定:

  • 多行:例如 {5-8}{3-10}{10-17}
  • 多个单行:例如 {4,7,9}
  • 多行与单行:例如 {4,7-13,16,23-27,40}

也可以使用 // [!code highlight] 注释实现行高亮。

export default {
  data () {
    return {
      msg: 'Highlighted!' // [!code highlight]
    }
  }
}

代码聚焦

export default {
  data () {
    return {
      msg: 'Focused!' // [!code focus]
    }
  }
}

代码块颜色差异

在某一行添加 // [!code --] 或 // [!code ++] 注释将会为该行创建 diff,同时保留代码块的颜色。

export default {
  data () {
    return {
      msg: 'Removed' // [!code --]
      msg: 'Added' // [!code ++]
    }
  }
}

高亮“错误”和“警告”

在某一行添加 // [!code warning] 或 // [!code error] 注释将会为该行相应的着色。

export default {
  data () {
    return {
      msg: 'Error', // [!code error]
      msg: 'Warning' // [!code warning]
    }
  }
}

行号

这里可以全局配置

// 启用行号
const line2 = 'This is line 2'
const line3 = 'This is line 3'

导入代码片段

可以通过下面的语法来从现有文件中导入代码片段:

<<< @/filepath

此语法同时支持行高亮: 可以像这样在大括号内({})指定语言: md

<<< @/filepath{highlightLines}
<<< @/snippets/snippet.cs{c#}

代码组

::: code-group

```js [config.js]
/**
 * @type {import('vitepress').UserConfig}
 */
const config = {
  // ...
}

export default config
import type { UserConfig } from 'vitepress'

const config: UserConfig = {
  // ...
}

export default config

:::


### 嵌套md
```md
# Docs

## Basics

<!--@include: ./parts/basics.md{3,}-->

数学公式

现在这是可选的。要启用它,需要安装 markdown-it-mathjax3,在配置文件中设置markdown.math 为 true

sh

npm add -D markdown-it-mathjax3
export default {
  markdown: {
    math: true
  }
}

高级配置

VitePress 使用 markdown-it 作为 Markdown 渲染器。上面提到的很多扩展功能都是通过自定义插件实现的。可以使用 .vitepress/config.js 中的 markdown 选项来进一步自定义 markdown-it 实例。

import { defineConfig } from 'vitepress'
import markdownItAnchor from 'markdown-it-anchor'
import markdownItFoo from 'markdown-it-foo'

export default defineConfig({
  markdown: {
    // markdown-it-anchor 的选项
    // https://github.com/valeriangalliat/markdown-it-anchor#usage
    anchor: {
      permalink: markdownItAnchor.permalink.headerLink()
    },
    // @mdit-vue/plugin-toc 的选项
    // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options
    toc: { level: [1, 2] },
    config: (md) => {
      // 使用更多的 Markdown-it 插件!
      md.use(markdownItFoo)
    }
  }
})

在md使用vue

模板语法

{{ 1 + 1 }}

<script> 和 <style>

Markdown 文件中的根级 <script> 和 <style> 标签与 Vue SFC 中的一样,包括 <script setup><style module> 等。这里的主要区别是没有 <template> 标签:所有其他根级内容都是 Markdown。另请注意,所有标签都应放在 frontmatter 之后

---
hello: world
---

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

## Markdown Content

The count is: {{ count }}

<button :class="$style.button" @click="count++">Increment</button>

<style module>
.button {
  color: red;
  font-weight: bold;
}
</style>

可以通过使用 v-pre 指令将它们包裹在 <span> 或其他元素中来转义 Vue 插值

This <span v-pre>{{ will be displayed as-is }}</span>

也可以将整个段落包装在 v-pre 自定义容器中:

md

::: v-pre
{{ This will be displayed as-is }}`
:::

使用 CSS 预处理器

VitePress 内置支持 CSS 预处理器:.scss.sass、.less.styl 和 .stylus 文件。无需为它们安装 Vite 专用插件,但必须安装相应的预处理器:

# .scss and .sass
npm install -D sass

# .less
npm install -D less

# .styl and .stylus
npm install -D stylus

然后可以在 Markdown 和主题组件中使用以下内容:

vue

<style lang="sass">
.title
  font-size: 20px
</style>

国际化

要使用内置的 i18n (国际化) 功能,需要创建类似于下面的目录结构:

docs/
├─ es/
│  ├─ foo.md
├─ fr/
│  ├─ foo.md
├─ foo.md

在viteptess/config.ts中

import { defineConfig } from 'vitepress'

export default defineConfig({
  // 共享属性和其他顶层内容...

  locales: {
    root: {
      label: 'English',
      lang: 'en'
    },
    fr: {
      label: 'French',
      lang: 'fr', // 可选,将作为 `lang` 属性添加到 `html` 标签中
      link: '/fr/guide' // 默认 /fr/ -- 显示在导航栏翻译菜单上,可以是外部的

      // 其余 locale 特定属性...
    }
  }
})

下面的属性能够被每个 locale 覆盖 (包括 root):

ts

interface LocaleSpecificConfig<ThemeConfig = any> {
  lang?: string
  dir?: string
  title?: string
  titleTemplate?: string | boolean
  description?: string
  head?: HeadConfig[] // 将与现有的头部条目合并,重复的元标签将自动删除
  themeConfig?: ThemeConfig // 会进行浅层合并,常见内容可放在顶层的 themeConfig 属性中
}

默认主题

主题的配置都在 vitepress.config.js 的themeConfig中

export default {
  lang: 'en-US',
  title: 'VitePress',
  description: 'Vite & Vue powered static site generator.',

  // 主题相关配置
  themeConfig: {
    logo: '/logo.svg',
    nav: [...],
    sidebar: { ... }
  }
}

i18nRouting

  • 类型:boolean

将本地语言更改为 zh 会将 URL 从 /foo(或 /en/foo/)更改为 /zh/foo。可以通过将 themeConfig.i18nRouting 设置为 false 来禁用此行为。

logo

导航栏上显示的 Logo,位于站点标题前。可以接受一个路径字符串,或者一个对象来设置在浅色/深色模式下不同的 Logo。

export default {
  themeConfig: {
    logo: '/logo.svg'
  }
}
type ThemeableImage =
  | string
  | { src: string; alt?: string }
  | { light: string; dark: string; alt?: string }

image.png

siteTitle

  • 类型:string | false

可以自定义此项以替换导航中的默认站点标题 (应用配置中的 title)。当设置为 false 时,导航中的标题将被禁用。这在当 logo 已经包含站点标题文本时很有用。

export default {
  themeConfig: {
    siteTitle: 'Hello World'
  }
}

image.png

nav 导航

image.png

text 是 nav 中显示的实际文本,而 link 是单击文本时将导航到的链接。对于链接,将路径设置为不带 .md 后缀的实际文件,并且始终以 / 开头。

导航链接也可以是下拉菜单。为此,请替换 link 选项,设置 items 数组。

js

export default {
  themeConfig: {
    nav: [
      { text: 'Guide', link: '/guide' },
      {
        text: 'Dropdown Menu',
        items: [
          { text: 'Item A', link: '/item-1' },
          { text: 'Item B', link: '/item-2' },
          { text: 'Item C', link: '/item-3' }
          {
              // 该部分的标题 
              text: 'Section A Title', 
              items: [ 
                  { text: 'Section A Item A', link: '...' }, 
                  { text: 'Section B Item B', link: '...' } 
              ]
          }
        ]
      }
    ]
  }
}

自定义链接的路由匹配状态

当前页面位于匹配路径下时,导航菜单项将突出显示。如果想自定义要匹配的路径,请将 activeMatch 属性和正则表达式定义为字符串值。

js

export default {
  themeConfig: {
    nav: [
      // 当用户位于 `/config/` 路径时,该链接处于激活状态
      {
        text: 'Guide',
        link: '/guide',
        activeMatch: '/config/'
      }
    ]
  }
}

自定义链接的“target”和“rel”属性

默认情况下,VitePress 会根据链接是否为外部链接自动判断 target 和 rel 属性。但如果愿意,也可以自定义它们。

js

export default {
  themeConfig: {
    nav: [
      {
        text: 'Merchandise',
        link: 'https://www.thegithubshop.com/',
        target: '_self',
        rel: 'sponsored'
      }
    ]
  }
}

在 HTML 中,rel属性是一个用于定义当前文档与链接目标之间关系的属性,它主要用于<a><link>等标签中,以下是其常见用法和取值介绍:

  • <a>标签中的使用

    • rel="noopener" :当链接指向一个新的页面时,使用noopener可以防止新页面通过window.opener访问当前页面的window对象,增强安全性,减少潜在的安全风险。例如:<a href="https://example.com" rel="noopener">链接文本</a>
    • rel="noreferrer" :使用noreferrer时,浏览器在加载目标页面时不会发送Referer头部信息,这可以保护用户的隐私,避免泄露当前页面的来源信息。比如:<a href="https://another-site.com" rel="noreferrer">另一个链接</a>
    • rel="nofollow" :告知搜索引擎不要追踪该链接,通常用于防止垃圾链接或者用户生成内容中的链接影响网站的权重和排名。如:<a href="https://spammy-site.com" rel="nofollow">垃圾链接示例</a>
    • rel="external" :表示链接指向外部网站,用于向用户和搜索引擎明确链接的目标是在当前网站之外。例如:<a href="https://outsidesite.com" rel="external">外部链接</a>
  • <link>标签中的使用

    • rel="stylesheet" :用于链接外部样式表,告诉浏览器该链接指向的是一个 CSS 文件,用于为当前页面设置样式。例如:<link rel="stylesheet" href="styles.css">
    • rel="icon" :用于指定网站的图标,通常是一个小的图像文件,显示在浏览器的标签页、收藏夹等位置。比如:<link rel="icon" href="favicon.ico">
    • rel="canonical" :用于指定页面的规范版本,帮助搜索引擎确定页面的主要版本,避免重复内容问题。例如:<link rel="canonical" href="https://www.example.com/correct-page">
    • rel="alternate" :用于指定页面的替代版本,比如不同语言版本或不同格式的页面。例如:<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/page">表示英语(美国)版本的页面。
  • 其他可能的取值和用途

    • rel="prev"rel="next" :用于表示页面之间的导航关系,prev表示上一页,next表示下一页,常用于分页导航。
    • rel="license" :用于链接到网站或文档的版权声明或使用许可页面。
    • rel="tag" :用于将当前文档与一个或多个标签相关联,类似于关键词,有助于分类和搜索。

你可以通过使用 component 选项在导航栏中包含自定义组件。component 键对应的值应为 Vue 组件名,并且必须使用 Theme.enhanceApp 全局注册。

自定义组件

export default {
  themeConfig: {
    nav: [
      {
        text: 'My Menu',
        items: [
          {
            component: 'MyCustomComponent',
            // 可选的 props 传递给组件
            props: {
              title: 'My Custom Component'
            }
          }
        ]
      },
      {
        component: 'AnotherCustomComponent'
      }
    ]
  }
}

sidebar

export type Sidebar = SidebarItem[] | SidebarMulti

export interface SidebarMulti {
  [path: string]: SidebarItem[]
}

export type SidebarItem = {
  text?: string //侧边栏项的文本标签
  link?: string //侧边栏项的链接
  items?: SidebarItem[] //侧边栏项的子项
  collapsed?: boolean // 默认不可折叠  `true`,则侧边栏组可折叠并且默认折叠 `false`,则侧边栏组可折叠但默认展开
}

useSidebar composable

返回侧边栏相关数据。返回的对象具有以下类型:

ts

export interface DocSidebar {
  isOpen: Ref<boolean>
  sidebar: ComputedRef<DefaultTheme.SidebarItem[]>
  sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
  hasSidebar: ComputedRef<boolean>
  hasAside: ComputedRef<boolean>
  leftAside: ComputedRef<boolean>
  isSidebarEnabled: ComputedRef<boolean>
  open: () => void
  close: () => void
  toggle: () => void
}

示例:

vue

<script setup>
import { useSidebar } from 'vitepress/theme'

const { hasSidebar } = useSidebar()
</script>

<template>
  <div v-if="hasSidebar">Only show when sidebar exists</div>
</template>

aside

  • 类型:boolean | 'left'
  • 默认值:true
  • 每个页面可以通过 frontmatter 覆盖

将此值设置为 false 可禁用 aside 容器。
将此值设置为 true 将在页面右侧渲染。
将此值设置为 left 将在页面左侧渲染。

如果想对所有页面禁用它,应该使用 outline: false

outline

  • 类型:Outline | Outline['level'] | false
  • 每个页面可以通过 frontmatter 覆盖层级

是否禁用aside

将此值设置为 false 可禁止渲染大纲容器。更多详情请参考该接口:

ts

interface Outline {
  /**
   * outline 中要显示的标题级别。
   * 单个数字表示只显示该级别的标题。
   * 如果传递的是一个元组,第一个数字是最小级别,第二个数字是最大级别。
   * `'deep'``[2, 6]` 相同,将显示从 `<h2>``<h6>` 的所有标题。
   *
   * @default 2
   */
  level?: number | [number, number] | 'deep'

  /**
   * 显示在 outline 上的标题。
   *
   * @default 'On this page'
   */
  label?: string
}

image.png

socialLinks

  • 类型:SocialLink[]

可以定义此选项以在导航栏中展示带有图标的社交帐户链接。

ts

export default {
  themeConfig: {
    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' },
      { icon: 'twitter', link: '...' },
      // 可以通过将 SVG 作为字符串传递来添加自定义图标:
      {
        icon: {
          svg: '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Dribbble</title><path d="M12...6.38z"/></svg>'
        },
        link: '...',
        // 也可以为无障碍添加一个自定义标签 (可选但推荐):
        ariaLabel: 'cool link'
      }
    ]
  }
}

ts

interface SocialLink {
  icon: string | { svg: string }
  link: string
  ariaLabel?: string
}

footer

  • 类型:Footer
  • 可以通过 frontmatter 进行覆盖。

页脚配置。可以添加 message 和 copyright。由于设计原因,仅当页面不包含侧边栏时才会显示页脚。

ts

export default {
  themeConfig: {
    footer: {
      message: 'Released under the MIT License.',
      copyright: 'Copyright © 2019-present Evan You'
    }
  }
}

ts

export interface Footer {
  message?: string
  copyright?: string
}

footer

export interface Footer {
  // 版权前显示的信息
  message?: string

  // 实际的版权文本
  copyright?: string
}

上面的配置也支持 HTML 字符串。所以,例如,如果想配置页脚文本有一些链接,可以调整配置如下:

ts

export default {
  themeConfig: {
    footer: {
      message: 'Released under the <a href="https://github.com/vuejs/vitepress/blob/main/LICENSE">MIT License</a>.',
      copyright: 'Copyright © 2019-present <a href="https://github.com/yyx990803">Evan You</a>'
    }
  }
}

WARNING

只有内联元素可以在 message 和 copyright 中使用,因为它们渲染在 <p> 元素中。如果想添加块元素,请考虑使用 layout-bottom 插槽。

请注意,当侧边栏可见时,不会显示页脚。

frontmatter 配置

可以使用 frontmatter 上的 footer 选项在单独页面上禁用此功能:

yaml

---
footer: false
---

editLink

  • 类型:EditLink
  • 每个页面可以通过 frontmatter 覆盖

编辑链接可让显示链接以编辑 Git 管理服务 (例如 GitHub 或 GitLab) 上的页面。有关详细信息,请参阅默认主题:编辑链接

image.png ts

export default {
  themeConfig: {
    editLink: {
      pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
      text: 'Edit this page on GitHub'
    }
  }
}

ts

export interface EditLink {
  pattern: string
  text?: string
}

lastUpdated

  • 类型:LastUpdatedOptions

允许自定义上次更新的文本和日期格式。

ts

export default {
  themeConfig: {
    lastUpdated: {
      text: 'Updated at',
      formatOptions: {
        dateStyle: 'full',
        timeStyle: 'medium'
      }
    }
  }
}

ts

export interface LastUpdatedOptions {
  /**
   * @default 'Last updated'
   */
  text?: string

  /**
   * @default
   * { dateStyle: 'short',  timeStyle: 'short' }
   */
  formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean }
}

algolia

  • 类型:AlgoliaSearch

支持使用 Algolia DocSearch 搜索站点文档。在默认主题:搜索 中了解更多信息。

ts

export interface AlgoliaSearchOptions extends DocSearchProps {
  locales?: Record<string, Partial<DocSearchProps>>
}

这里查看完整配置。

carbonAds

开源项目广告 |碳广告

  • 类型:CarbonAdsOptions

一个配置即可展示 Carbon Ads

ts

export default {
  themeConfig: {
    carbonAds: {
      code: 'your-carbon-code',
      placement: 'your-carbon-placement'
    }
  }
}

ts

export interface CarbonAdsOptions {
  code: string
  placement: string
}

在 Default Theme: Carbon Ads 中了解更多信息。

docFooter

  • 类型:DocFooter

可用于自定义出现在上一页和下一页链接上方的文本。如果不是用英语编写文档,这很有帮助。也可用于全局禁用上一页/下一页链接。如果想有选择地启用/禁用上一个/下一个链接,可以使用 frontmatter

ts

export default {
  themeConfig: {
    docFooter: {
      prev: '上一页',
      next: '下一页'
    }
  }
}

ts

export interface DocFooter {
  prev?: string | false
  next?: string | false
}

darkModeSwitchLabel

  • 类型:string
  • 默认值:Appearance

用于自定义深色模式开关标签,该标签仅在移动端视图中显示。

lightModeSwitchTitle

  • 类型:string
  • 默认值:Switch to light theme

用于自定义悬停时显示的浅色模式开关标题。

darkModeSwitchTitle

  • 类型:string
  • 默认值:Switch to dark theme

用于自定义悬停时显示的深色模式开关标题。

sidebarMenuLabel

  • 类型:string
  • 默认值:Menu

用于自定义侧边栏菜单标签,该标签仅在移动端视图中显示。

sidebarMenuLabel

  • 类型:string
  • 默认值:Menu

用于自定义侧边栏菜单标签,该标签仅在移动端视图中显示。

returnToTopLabel

  • 类型:string
  • 默认值:Return to top

用于自定义返回顶部按钮的标签,该标签仅在移动端视图中显示。

langMenuLabel

  • 类型:string
  • 默认值:Change language

用于自定义导航栏中语言切换按钮的 aria-label,仅当使用 i18n 时才使用此选项。

externalLinkIcon

  • 类型:boolean
  • 默认值:false

是否在 markdown 中的外部链接旁显示外部链接图标。

主页

Hero 部分

Hero 部分位于主页顶部。以下是配置 Hero 的方法。

---
layout: home

hero:
  name: VitePress
  text: Vite & Vue powered static site generator.
  tagline: Lorem ipsum...
  image:
    src: /logo.png
    alt: VitePress
  actions:
    - theme: brand
      text: Get Started
      link: /guide/what-is-vitepress
    - theme: alt
      text: View on GitHub
      link: https://github.com/vuejs/vitepress
---

ts

interface Hero {
  // `text` 上方的字符,带有品牌颜色
  // 预计简短,例如产品名称
  name?: string

  // hero 部分的主要文字,
  // 被定义为 `h1` 标签
  text: string

  // `text` 下方的标语
  tagline?: string

  // text 和 tagline 区域旁的图片
  image?: ThemeableImage

  // 主页 hero 部分的操作按钮
  actions?: HeroAction[]
}

type ThemeableImage =
  | string
  | { src: string; alt?: string }
  | { light: string; dark: string; alt?: string }

interface HeroAction {
  // 按钮的颜色主题,默认为 `brand`
  theme?: 'brand' | 'alt'

  // 按钮的标签
  text: string

  // 按钮的目标链接
  link: string

  // 链接的 target 属性
  target?: string

  // 链接的 rel 属性
  rel?: string
}

自定义 name 的颜色

VitePress 通过 (--vp-c-brand-1) 设置 name 的颜色。但是,可以通过覆盖 --vp-home-hero-name-color 变量来自定义此颜色。

css

:root {
  --vp-home-hero-name-color: blue;
}

也可以通过组合 --vp-home-hero-name-background 来进一步自定义 name 为渐变色。

css

:root {
  --vp-home-hero-name-color: transparent;
  --vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
}

Features 部分

在 Features 部分,可以在 Hero 部分之后列出任意数量的 Feature。可以在 frontmatter 中配置 features

可以为每个 feature 提供一个图标,可以是表情符号或任何类型的图像。当配置的图标是图片(svg, png, jpeg...)时,必须提供合适的宽度和高度的图标;还可以在需要时配置其描述、固有大小以及深色和浅色主题下的不同表现。

yaml

---
layout: home

features:
  - icon: 🛠️
    title: Simple and minimal, always
    details: Lorem ipsum...
  - icon:
      src: /cool-feature-icon.svg
    title: Another cool feature
    details: Lorem ipsum...
  - icon:
      dark: /dark-feature-icon.svg
      light: /light-feature-icon.svg
    title: Another cool feature
    details: Lorem ipsum...
---

ts

interface Feature {
  // 在每个 feature 框中显示图标
  icon?: FeatureIcon

  // feature 的标题
  title: string

  // feature 的详情
  details: string

  // 点击 feature 组件时的链接,可以是内部链接,也可以是外部链接。
  //
  //
  // 例如 `guide/reference/default-theme-home-page` 或 `https://example.com`
  link?: string

  // feature 组件内显示的链接文本,最好与 `link` 选项一起使用
  //
  //
  // 例如 `Learn more`, `Visit page` 等
  linkText?: string

  // `link` 选项的链接 rel 属性
  //
  // 例如 `external`
  rel?: string

  // `link` 选项的链接 target 属性
  target?: string
}

type FeatureIcon =
  | string
  | { src: string; alt?: string; width?: string; height: string }
  | {
      light: string
      dark: string
      alt?: string
      width?: string
      height: string
    }

布局

可以通过设置页面 frontmatter 选项来选择页面布局。有 3 种布局选项 docpage 和 home。如果未指定任何内容,则该页面将被视为 doc 页面。

doc 是默认布局,它将整个 Markdown 内容设置为“documentation”外观。它的工作原理是将整个内容包装在 css vp-doc 类中,并将样式应用于它下面的元素。

几乎所有通用元素,例如 p, 或 h2 都有特殊的样式。因此,请记住,如果在 Markdown 内容中添加任何自定义 HTML,这些内容也会受到这些样式的影响。

它还提供下面列出的文档特定功能。这些功能仅在此布局中启用。

page 布局

page 被视为“空白页”。Markdown 仍然会被解析,所有的 Markdown 扩展 都和 doc 布局一样运行,但它没有任何默认样式。

page 布局将使可以自行设计所有内容,而不会受 VitePress 主题影响。当想要创建自己的自定义页面时,这很有用。

请注意,即使在此布局中,如果页面具有匹配的侧边栏配置,侧边栏仍会显示。

home 布局

home 将生成模板化的“主页”。在此布局中,可以设置额外的选项,例如 hero 和 features 以进一步自定义内容。请访问默认主题: 主页了解更多详情。

无布局

如果不想要任何布局,可以通过 frontmatter 传递 layout: false。如果想要一个完全可自定义的登录页面(默认情况下没有任何侧边栏、导航栏或页脚),此选项很有用。

自定义布局

也可以使用自定义布局:

md

---
layout: foo
---

这将在上下文中查找注册名为 foo 的组件。例如,可以在 .vitepress/theme/index.ts中全局注册组件:

ts

import DefaultTheme from 'vitepress/theme'
import Foo from './Foo.vue'

export default {
  extends: DefaultTheme,
  enhanceApp({ app }) {
    app.component('foo', Foo)
  }
}

徽标

用法

可以使用全局组件 Badge 。

html

### Title <Badge type="info" text="default" />
### Title <Badge type="tip" text="^1.9.0" />
### Title <Badge type="warning" text="beta" />
### Title <Badge type="danger" text="caution" />

自定义不同类型徽标的背景色

可以通过覆盖 css 来自定义不同类型 <Badge /> 的样式。以下是默认值。

css

:root {
  --vp-badge-info-border: transparent;
  --vp-badge-info-text: var(--vp-c-text-2);
  --vp-badge-info-bg: var(--vp-c-default-soft);

  --vp-badge-tip-border: transparent;
  --vp-badge-tip-text: var(--vp-c-brand-1);
  --vp-badge-tip-bg: var(--vp-c-brand-soft);

  --vp-badge-warning-border: transparent;
  --vp-badge-warning-text: var(--vp-c-warning-1);
  --vp-badge-warning-bg: var(--vp-c-warning-soft);

  --vp-badge-danger-border: transparent;
  --vp-badge-danger-text: var(--vp-c-danger-1);
  --vp-badge-danger-bg: var(--vp-c-danger-soft);
}

<Badge>

<Badge> 组件接受以下属性:

ts

interface Props {
  // 当传递 `<slot>` 时,该值将被忽略
  text?: string

  // 默认为 `tip`.
  type?: 'info' | 'tip' | 'warning' | 'danger'
}

团队页

在页面中显示团队成员

你可以在任何页面上使用从 vitepress/theme 暴露出的公共组件 <VPTeamMembers> 显示团队成员。

html

<script setup>
import { VPTeamMembers } from 'vitepress/theme'

const members = [
  {
    avatar: 'https://www.github.com/yyx990803.png',
    name: 'Evan You',
    title: 'Creator',
    links: [
      { icon: 'github', link: 'https://github.com/yyx990803' },
      { icon: 'twitter', link: 'https://twitter.com/youyuxi' }
    ]
  },
  ...
]
</script>

# Our Team

Say hello to our awesome team.

<VPTeamMembers size="small" :members="members" />

最后更新于

js

export default {
  lastUpdated: true
}

搜索

得益于 minisearch,VitePress 支持使用浏览器内索引进行模糊全文搜索。要启用此功能,只需在 .vitepress/config.ts 文件中将 themeConfig.search.provider 选项设置为 'local' 即可:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local'
    }
  }
})

或者,你可以使用 Algolia DocSearch 或一些社区插件,例如:www.npmjs.com/package/vit… 或者 www.npmjs.com/package/vit…

i18n

你可以使用这样的配置来使用多语言搜索:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local',
      options: {
        locales: {
          zh: {
            translations: {
              button: {
                buttonText: '搜索文档',
                buttonAriaLabel: '搜索文档'
              },
              modal: {
                noResultsText: '无法找到相关结果',
                resetButtonTitle: '清除查询条件',
                footer: {
                  selectText: '选择',
                  navigateText: '切换'
                }
              }
            }
          }
        }
      }
    }
  }
})

MiniSearch 配置项

你可以像这样配置 MiniSearch :

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local',
      options: {
        miniSearch: {
          /**
           * @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
           */
          options: {
            /* ... */
          },
          /**
           * @type {import('minisearch').SearchOptions}
           * @default
           * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
           */
          searchOptions: {
            /* ... */
          }
        }
      }
    }
  }
})

参阅 MiniSearch 文档了解更多信息。

自定义渲染内容

可以在索引之前自定义用于渲染 Markdown 内容的函数:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local',
      options: {
        /**
         * @param {string} src
         * @param {import('vitepress').MarkdownEnv} env
         * @param {import('markdown-it-async')} md
         */
        async _render(src, env, md) {
          // 返回 html 字符串
        }
      }
    }
  }
})

该函数将从客户端站点数据中剥离,因此你可以在其中使用 Node.js API。

示例:从搜索中排除页面

你可以通过将 search: false 添加到页面的 frontmatter 来从搜索中排除页面。或者:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local',
      options: {
        async _render(src, env, md) {
          const html = await md.renderAsync(src, env)
          if (env.frontmatter?.search === false) return ''
          if (env.relativePath.startsWith('some/path')) return ''
          return html
        }
      }
    }
  }
})

注意

如果提供了自定义的 _render 函数,你需要自己处理 search: false 的 frontmatter。此外,在调用 md.renderAsync 之前,env 对象不会完全填充,因此对可选 env 属性 (如 frontmatter) 的任何检查都应该在此之后完成。

示例:转换内容——添加锚点

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'local',
      options: {
        async _render(src, env, md) {
          const html = await md.renderAsync(src, env)
          if (env.frontmatter?.title)
            return await md.renderAsync(`# ${env.frontmatter.title}`) + html
          return html
        }
      }
    }
  }
})

Algolia Search

VitePress 支持使用 Algolia DocSearch 搜索文档站点。请参阅他们的入门指南。在你的 .vitepress/config.ts 中,你至少需要提供以下内容才能使其正常工作:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'algolia',
      options: {
        appId: '...',
        apiKey: '...',
        indexName: '...'
      }
    }
  }
})

i18n

你可以使用这样的配置来使用多语言搜索:

ts

import { defineConfig } from 'vitepress'

export default defineConfig({
  themeConfig: {
    search: {
      provider: 'algolia',
      options: {
        appId: '...',
        apiKey: '...',
        indexName: '...',
        locales: {
          zh: {
            placeholder: '搜索文档',
            translations: {
              button: {
                buttonText: '搜索文档',
                buttonAriaLabel: '搜索文档'
              },
              modal: {
                searchBox: {
                  resetButtonTitle: '清除查询条件',
                  resetButtonAriaLabel: '清除查询条件',
                  cancelButtonText: '取消',
                  cancelButtonAriaLabel: '取消'
                },
                startScreen: {
                  recentSearchesTitle: '搜索历史',
                  noRecentSearchesText: '没有搜索历史',
                  saveRecentSearchButtonTitle: '保存至搜索历史',
                  removeRecentSearchButtonTitle: '从搜索历史中移除',
                  favoriteSearchesTitle: '收藏',
                  removeFavoriteSearchButtonTitle: '从收藏中移除'
                },
                errorScreen: {
                  titleText: '无法获取结果',
                  helpText: '你可能需要检查你的网络连接'
                },
                footer: {
                  selectText: '选择',
                  navigateText: '切换',
                  closeText: '关闭',
                  searchByText: '搜索提供者'
                },
                noResultsScreen: {
                  noResultsText: '无法找到相关结果',
                  suggestedQueryText: '你可以尝试查询',
                  reportMissingResultsText: '你认为该查询应该有结果?',
                  reportMissingResultsLinkText: '点击反馈'
                }
              }
            }
          }
        }
      }
    }
  }
})

这些选项可以被覆盖。请参阅 Algolia 官方文档以了解更多信息。

爬虫配置

以下是基于此站点使用的示例配置:

ts

new Crawler({
  appId: '...',
  apiKey: '...',
  rateLimit: 8,
  startUrls: ['https://vitepress.dev/'],
  renderJavaScript: false,
  sitemaps: [],
  exclusionPatterns: [],
  ignoreCanonicalTo: false,
  discoveryPatterns: ['https://vitepress.dev/**'],
  schedule: 'at 05:10 on Saturday',
  actions: [
    {
      indexName: 'vitepress',
      pathsToMatch: ['https://vitepress.dev/**'],
      recordExtractor: ({ $, helpers }) => {
        return helpers.docsearch({
          recordProps: {
            lvl1: '.content h1',
            content: '.content p, .content li',
            lvl0: {
              selectors: 'section.has-active div h2',
              defaultValue: 'Documentation'
            },
            lvl2: '.content h2',
            lvl3: '.content h3',
            lvl4: '.content h4',
            lvl5: '.content h5'
          },
          indexHeadings: true
        })
      }
    }
  ],
  initialIndexSettings: {
    vitepress: {
      attributesForFaceting: ['type', 'lang'],
      attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
      attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
      attributesToSnippet: ['content:10'],
      camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
      searchableAttributes: [
        'unordered(hierarchy_radio_camel.lvl0)',
        'unordered(hierarchy_radio.lvl0)',
        'unordered(hierarchy_radio_camel.lvl1)',
        'unordered(hierarchy_radio.lvl1)',
        'unordered(hierarchy_radio_camel.lvl2)',
        'unordered(hierarchy_radio.lvl2)',
        'unordered(hierarchy_radio_camel.lvl3)',
        'unordered(hierarchy_radio.lvl3)',
        'unordered(hierarchy_radio_camel.lvl4)',
        'unordered(hierarchy_radio.lvl4)',
        'unordered(hierarchy_radio_camel.lvl5)',
        'unordered(hierarchy_radio.lvl5)',
        'unordered(hierarchy_radio_camel.lvl6)',
        'unordered(hierarchy_radio.lvl6)',
        'unordered(hierarchy_camel.lvl0)',
        'unordered(hierarchy.lvl0)',
        'unordered(hierarchy_camel.lvl1)',
        'unordered(hierarchy.lvl1)',
        'unordered(hierarchy_camel.lvl2)',
        'unordered(hierarchy.lvl2)',
        'unordered(hierarchy_camel.lvl3)',
        'unordered(hierarchy.lvl3)',
        'unordered(hierarchy_camel.lvl4)',
        'unordered(hierarchy.lvl4)',
        'unordered(hierarchy_camel.lvl5)',
        'unordered(hierarchy.lvl5)',
        'unordered(hierarchy_camel.lvl6)',
        'unordered(hierarchy.lvl6)',
        'content'
      ],
      distinct: true,
      attributeForDistinct: 'url',
      customRanking: [
        'desc(weight.pageRank)',
        'desc(weight.level)',
        'asc(weight.position)'
      ],
      ranking: [
        'words',
        'filters',
        'typo',
        'attribute',
        'proximity',
        'exact',
        'custom'
      ],
      highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
      highlightPostTag: '</span>',
      minWordSizefor1Typo: 3,
      minWordSizefor2Typos: 7,
      allowTyposOnNumericTokens: false,
      minProximity: 1,
      ignorePlurals: true,
      advancedSyntax: true,
      attributeCriteriaComputedByMinProximity: true,
      removeWordsIfNoResults: 'allOptional'
    }
  }
})

vitepress 显示更新日志

const { execSync } = require('child_process');
const fs = require('fs');

// 获取 Git 日志
const gitLog = execSync('git log --pretty=short', { encoding: 'utf8' });

// 生成更新日志内容
const changelogContent = `# 更新日志\n\n${gitLog}`;

// 将更新日志内容写入文件
fs.writeFileSync('/etc/changelog.md', changelogContent);