>
+}
+```
+
+在[这里](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)查看完整配置。
+
+## carbonAds {#carbon-ads}
+
+- 类型:`CarbonAdsOptions`
+
+一个配置即可展示 [Carbon Ads](https://www.carbonads.net/)。
+
+```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](./default-theme-carbon-ads) 中了解更多信息。
+
+## docFooter
+
+- 类型:`DocFooter`
+
+可用于自定义出现在上一页和下一页链接上方的文本。如果不是用英语编写文档,这很有帮助。也可用于全局禁用上一页/下一页链接。如果想有选择地启用/禁用上一个/下一个链接,可以使用 [frontmatter](./default-theme-prev-next-links)。
+
+```ts
+export default {
+ themeConfig: {
+ docFooter: {
+ prev: 'Pagina prior',
+ next: 'Proxima pagina'
+ }
+ }
+}
+```
+
+```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`
+
+用于自定义侧边栏菜单标签,该标签仅在移动端视图中显示。
+
+## returnToTopLabel
+
+- 类型:`string`
+- 默认值:`Return to top`
+
+用于自定义返回顶部按钮的标签,该标签仅在移动端视图中显示。
+
+## langMenuLabel
+
+- 类型:`string`
+- 默认值:`Change language`
+
+用于自定义导航栏中语言切换按钮的 aria-label,仅当使用 [i18n](../guide/i18n) 时才使用此选项。
+
+## externalLinkIcon
+
+- 类型:`boolean`
+- 默认值:`false`
+
+是否在 markdown 中的外部链接旁显示外部链接图标。
diff --git a/docs/zh/reference/default-theme-edit-link.md b/docs/zh/reference/default-theme-edit-link.md
new file mode 100644
index 00000000..92f3cd25
--- /dev/null
+++ b/docs/zh/reference/default-theme-edit-link.md
@@ -0,0 +1,60 @@
+# 编辑链接 {#edit-link}
+
+## 站点级配置 {#site-level-config}
+
+编辑链接让你可以显示一个链接,以在 GitHub 或 GitLab 等 Git 管理服务上编辑页面。要启用它,请将 `themeConfig.editLink` 选项添加到配置中。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
+ }
+ }
+}
+```
+
+`pattern` 选项定义链接的 URL 结构,并且 `:path` 将被替换为页面路径。
+
+你还可以放置一个接受 [`PageData`](./runtime-api#usedata) 作为参数并返回 URL 字符串的纯函数。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: ({ filePath }) => {
+ if (filePath.startsWith('packages/')) {
+ return `https://github.com/acme/monorepo/edit/main/${filePath}`
+ } else {
+ return `https://github.com/acme/monorepo/edit/main/docs/${filePath}`
+ }
+ }
+ }
+ }
+}
+```
+
+它不应该有副作用,也不应该访问其范围之外的任何东西,因为它将在浏览器中被序列化和执行。
+
+默认情况下,这将在文档页面底部添加链接文本“Edit this page”。可以通过定义 `text` 选项来自定义此文本。
+
+```js
+export default {
+ themeConfig: {
+ editLink: {
+ pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
+ text: 'Edit this page on GitHub'
+ }
+ }
+}
+```
+
+## frontmatter 配置 {#frontmatter-config}
+
+可以使用 frontmatter 上的 `editLink` 选项单独禁用某个页面的编辑链接:
+
+```yaml
+---
+editLink: false
+---
+```
diff --git a/docs/zh/reference/default-theme-footer.md b/docs/zh/reference/default-theme-footer.md
new file mode 100644
index 00000000..7499089f
--- /dev/null
+++ b/docs/zh/reference/default-theme-footer.md
@@ -0,0 +1,53 @@
+# 页脚 {#footer}
+
+配置好 `themeConfig.footer`,VitePress 将在全局页面底部显示页脚。
+
+```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
+}
+```
+
+上面的配置也支持 HTML 字符串。所以,例如,如果想配置页脚文本有一些链接,可以调整配置如下:
+
+```ts
+export default {
+ themeConfig: {
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2019-present Evan You'
+ }
+ }
+}
+```
+
+::: warning
+只有内联元素可以在 `message` 和 `copyright` 中使用,因为它们渲染在 `` 元素中。如果想添加块元素,请考虑使用 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 插槽。
+:::
+
+请注意,当[侧边栏](./default-theme-sidebar)可见时,不会显示页脚。
+
+## frontmatter 配置 {#frontmatter-config}
+
+可以使用 frontmatter 上的 `footer` 选项在单独页面上禁用此功能:
+
+```yaml
+---
+footer: false
+---
+```
diff --git a/docs/zh/reference/default-theme-home-page.md b/docs/zh/reference/default-theme-home-page.md
new file mode 100644
index 00000000..ac5848c4
--- /dev/null
+++ b/docs/zh/reference/default-theme-home-page.md
@@ -0,0 +1,155 @@
+# 主页 {#home-page}
+
+VitePress 默认主题提供了一个首页布局,也可以在[此站点首页](../)看到。可以通过 [frontmatter](./frontmatter-config) 指定 `layout: home` 在任何页面上使用它
+
+```yaml
+---
+layout: home
+---
+```
+
+但是,仅此选项不会有太大作用。可以通过设置其他选项(例如 `hero` 和 `features`)向主页添加几个不同的预模板化。
+
+## Hero 部分 {#hero-section}
+
+Hero section 位于主页顶部。以下是配置 Hero 的方法。
+
+```yaml
+---
+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
+}
+```
+
+### 自定义 name 的颜色 {#customizing-the-name-color}
+
+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-section}
+
+在 Features section,可以在 Hero section 之后列出任意数量的 Features。可以在 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
+}
+
+type FeatureIcon =
+ | string
+ | { src: string; alt?: string; width?: string; height: string }
+ | {
+ light: string
+ dark: string
+ alt?: string
+ width?: string
+ height: string
+ }
+```
\ No newline at end of file
diff --git a/docs/zh/reference/default-theme-last-updated.md b/docs/zh/reference/default-theme-last-updated.md
new file mode 100644
index 00000000..aa519731
--- /dev/null
+++ b/docs/zh/reference/default-theme-last-updated.md
@@ -0,0 +1,27 @@
+# 最后更新于 {#last-updated}
+
+最近一条内容的更新时间会显示在页面右下角。要启用它,请将 `lastUpdated` 选项添加到配置中。
+
+::: tip
+你必须提交 markdown 文件才能看到最近更新时间。
+:::
+
+## 全局配置 {#site-level-config}
+
+```js
+export default {
+ lastUpdated: true
+}
+```
+
+## frontmatter 配置 {#frontmatter-config}
+
+可以使用 frontmatter 上的 `lastUpdated` 选项单独禁用某个页面的最后更新展示:
+
+```yaml
+---
+lastUpdated: false
+---
+```
+
+另请参阅[默认主题:最近更新时间](./default-theme-config#lastupdated) 了解更多详细信息。主题级别的任何 [truthy](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy) 值也将启用该功能,除非在站点或页面级别明确禁用。
diff --git a/docs/zh/reference/default-theme-layout.md b/docs/zh/reference/default-theme-layout.md
new file mode 100644
index 00000000..1353ab46
--- /dev/null
+++ b/docs/zh/reference/default-theme-layout.md
@@ -0,0 +1,62 @@
+# 布局 {#layout}
+
+可以通过设置页面 [frontmatter](./frontmatter-config) 选项来选择页面布局。有 3 种布局选项 `doc`、`page` 和 `home`。如果未指定任何内容,则该页面将被视为 `doc` 页面。
+
+```yaml
+---
+layout: doc
+---
+```
+
+## doc 布局 {#doc-layout}
+
+`doc` 是默认布局,它将整个 Markdown 内容设置为“documentation”外观。它的工作原理是将整个内容包装在 css `vp-doc` 类中,并将样式应用于它下面的元素。
+
+几乎所有通用元素,例如 `p`, 或 `h2` 都有特殊的样式。因此,请记住,如果在 Markdown 内容中添加任何自定义 HTML,这些内容也会受到这些样式的影响。
+
+它还提供下面列出的文档特定功能。这些功能仅在此布局中启用。
+
+- [编辑链接](./default-theme-edit-link)
+- [上下页链接](./default-theme-prev-next-links)
+- [大纲](./default-theme-config#outline)
+- [Carbon Ads](./default-theme-carbon-ads)
+
+## page 布局 {#page-layout}
+
+`page` 被视为“空白页”。Markdown 仍然会被解析,所有的 [Markdown 拓展](../guide/markdown) 都和 `doc` 布局一样运行,但它没有任何默认样式。
+
+`page` 布局将使可以自行设计所有内容,而不会受 VitePress 主题影响。当想要创建自己的自定义页面时,这很有用。
+
+请注意,即使在此布局中,如果页面具有匹配的侧边栏配置,侧边栏仍会显示。
+
+## home 布局 {#home-layout}
+
+`home` 将生成模板化的“主页”。在此布局中,可以设置额外的选项,例如 `hero` 和 `features` 以进一步自定义内容。请访问[默认主题: 主页](./default-theme-home-page)了解更多详情。
+
+## 无布局 {#no-layout}
+
+如果不想要任何布局,可以通过 frontmatter 传递 `layout: false`。如果想要一个完全可自定义的登录页面(默认情况下没有任何侧边栏、导航栏或页脚),此选项很有用。
+
+## 自定义布局 {#custom-layout}
+
+也可以使用自定义布局:
+
+```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)
+ }
+}
+```
diff --git a/docs/zh/reference/default-theme-nav.md b/docs/zh/reference/default-theme-nav.md
new file mode 100644
index 00000000..ca844c65
--- /dev/null
+++ b/docs/zh/reference/default-theme-nav.md
@@ -0,0 +1,161 @@
+# 导航栏 {#nav}
+
+Nav 是显示在页面顶部的导航栏。它包含站点标题、全局菜单链接等。
+
+## 站点标题和图标 {#site-title-and-logo}
+
+默认情况下,nav 显示 [`config.title`](./site-config#title) 作为站点的标题。如果想更改导航栏上显示的内容,可以在 `themeConfig.siteTitle` 选项中定义自定义文本。
+
+```js
+export default {
+ themeConfig: {
+ siteTitle: 'My Custom Title'
+ }
+}
+```
+
+如果站点有图标,则可以通过传递图片路径来显示它。应该将图标直接放在 `public` 中,并赋值该绝对路径。
+
+```js
+export default {
+ themeConfig: {
+ logo: '/my-logo.svg'
+ }
+}
+```
+
+添加图标时,它会与站点标题一起显示。如果只需要图标并且想要隐藏站点标题文本,请将 `siteTitle` 选项设置为 `false`。
+
+```js
+export default {
+ themeConfig: {
+ logo: '/my-logo.svg',
+ siteTitle: false
+ }
+}
+```
+
+如果想添加 `alt` 属性或根据暗/亮模式自定义它,还可以将图标作为对象传递。有关详细信息,请参阅 [`themeConfig.logo`](./default-theme-config#logo)。
+
+## 导航链接 {#navigation-links}
+
+可以定义 `themeConfig.nav` 选项以将链接添加到导航栏。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ { text: 'Guide', link: '/guide' },
+ { text: 'Config', link: '/config' },
+ { text: 'Changelog', link: 'https://github.com/...' }
+ ]
+ }
+}
+```
+
+`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' }
+ ]
+ }
+ ]
+ }
+}
+```
+
+请注意,下拉菜单标题(上例中的 `下拉菜单`)不能具有 `link` 属性,因为它是打开下拉对话框的按钮。
+
+还可以通过传入更多嵌套项来进一步向下拉菜单项添加“sections”。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ { text: 'Guide', link: '/guide' },
+ {
+ text: 'Dropdown Menu',
+ items: [
+ {
+ // 该部分的标题
+ text: 'Section A Title',
+ items: [
+ { text: 'Section A Item A', link: '...' },
+ { text: 'Section B Item B', link: '...' }
+ ]
+ }
+ ]
+ },
+ {
+ text: 'Dropdown Menu',
+ items: [
+ {
+ // 也可以省略标题
+ items: [
+ { text: 'Section A Item A', link: '...' },
+ { text: 'Section B Item B', link: '...' }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+### 自定义链接的路由匹配状态 {#customize-link-s-active-state}
+
+当前页面位于匹配路径下时,导航菜单项将突出显示。如果 想自定义要匹配的路径,请将 `activeMatch` 属性和正则表达式定义为字符串值。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ // 当用户位于 `/config/` 路径时,该链接处于激活状态
+ {
+ text: 'Guide',
+ link: '/guide',
+ activeMatch: '/config/'
+ }
+ ]
+ }
+}
+```
+
+::: warning
+`activeMatch` 应为正则表达式字符串,但必须将其定义为字符串。我们不能在这里使用实际的 RegExp 对象,因为它在构建期间不可序列化。
+:::
+
+### 自定义链接的“target”和“rel”属性 {#customize-link-s-target-and-rel-attributes}
+
+默认情况下,VitePress 会根据链接是否为外部链接自动判断 `target` 和 `rel` 属性。但如果愿意,也可以自定义它们。
+
+```js
+export default {
+ themeConfig: {
+ nav: [
+ {
+ text: 'Merchandise',
+ link: 'https://www.thegithubshop.com/',
+ target: '_self',
+ rel: 'sponsored'
+ }
+ ]
+ }
+}
+```
+
+## 社交链接 {#social-links}
+
+参考 [`socialLinks`](./default-theme-config#sociallinks)。
diff --git a/docs/zh/reference/default-theme-prev-next-links.md b/docs/zh/reference/default-theme-prev-next-links.md
new file mode 100644
index 00000000..cdbe8434
--- /dev/null
+++ b/docs/zh/reference/default-theme-prev-next-links.md
@@ -0,0 +1,43 @@
+# 上下页链接 {#prev-next-links}
+
+可以自定义上一页和下一页的文本和链接 (显示在文档页脚处)。如果要使其与侧边栏上的文本不同,这会很有帮助。此外,你可能会发现,要禁用未包含在侧边栏中的页面的页脚或链接时,这很有用。
+
+## prev
+
+- 类型:`string | false | { text?: string; link?: string }`
+
+- 说明:
+
+ 指定要在指向上一页的链接上显示的文本/链接。如果没有在 frontmatter 中设置它,文本/链接将从侧边栏配置中推断出来。
+
+- 示例:
+
+ - 仅自定义文本:
+
+ ```yaml
+ ---
+ prev: 'Get Started | Markdown'
+ ---
+ ```
+
+ - 自定义文本和链接:
+
+ ```yaml
+ ---
+ prev:
+ text: 'Markdown'
+ link: '/guide/markdown'
+ ---
+ ```
+
+ - 隐藏上一页:
+
+ ```yaml
+ ---
+ prev: false
+ ---
+ ```
+
+## next
+
+与 `prev` 相同,但用于下一页。
diff --git a/docs/zh/reference/default-theme-search.md b/docs/zh/reference/default-theme-search.md
new file mode 100644
index 00000000..4449a4ce
--- /dev/null
+++ b/docs/zh/reference/default-theme-search.md
@@ -0,0 +1,379 @@
+---
+outline: deep
+---
+
+# 搜索 {#search}
+
+## 本地搜索 {#local-search}
+
+得益于 [minisearch](https://github.com/lucaong/minisearch/),VitePress 支持使用浏览器内索引进行模糊全文搜索。要启用此功能,只需在 `.vitepress/config.ts` 文件中将 `themeConfig.search.provider` 选项设置为 `'local'` 即可:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local'
+ }
+ }
+})
+```
+
+示例结果:
+
+
+
+或者,你可以使用 [Algolia DocSearch](#algolia-search) 或一些社区插件,例如: 或者 。
+
+### i18n {#local-search-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 配置项 {#mini-search-options}
+
+你可以像这样配置 MiniSearch :
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ miniSearch: {
+ /**
+ * @type {Pick}
+ */
+ options: {
+ /* ... */
+ },
+ /**
+ * @type {import('minisearch').SearchOptions}
+ * @default
+ * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
+ */
+ searchOptions: {
+ /* ... */
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+参阅 [MiniSearch 文档](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)了解更多信息。
+
+### 自定义渲染内容 {#custom-content-renderer}
+
+可以在索引之前自定义用于渲染 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')} md
+ */
+ _render(src, env, md) {
+ // 返回 html 字符串
+ }
+ }
+ }
+ }
+})
+```
+
+该函数将从客户端站点数据中剥离,因此你可以在其中使用 Node.js API。
+
+#### 示例:从搜索中排除页面 {#example-excluding-pages-from-search}
+
+你可以通过将 `search: false` 添加到页面的 `frontmatter` 来从搜索中排除页面。或者:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ _render(src, env, md) {
+ const html = md.render(src, env)
+ if (env.frontmatter?.search === false) return ''
+ if (env.relativePath.startsWith('some/path')) return ''
+ return html
+ }
+ }
+ }
+ }
+})
+```
+
+::: warning 注意
+如果提供了自定义的 `_render` 函数,你需要自己处理 `search: false` 的 frontmatter。此外,在调用 `md.render` 之前,`env` 对象不会完全填充,因此对可选 `env` 属性(如 `frontmatter` )的任何检查都应该在此之后完成。
+:::
+
+#### 示例:转换内容-添加锚点{#example-transforming-content-adding-anchors}
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'local',
+ options: {
+ _render(src, env, md) {
+ const html = md.render(src, env)
+ if (env.frontmatter?.title)
+ return md.render(`# ${env.frontmatter.title}`) + html
+ return html
+ }
+ }
+ }
+ }
+})
+```
+
+## Algolia Search {#algolia-search}
+
+VitePress 支持使用 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch) 搜索文档站点。请参阅他们的入门指南。在你的 `.vitepress/config.ts` 中,你至少需要提供以下内容才能使其正常工作:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ search: {
+ provider: 'algolia',
+ options: {
+ appId: '...',
+ apiKey: '...',
+ indexName: '...'
+ }
+ }
+ }
+})
+```
+
+### i18n {#algolia-search-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: '点击反馈'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+})
+```
+
+[这些选项](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)可以被覆盖。请参阅 Algolia 官方文档以了解更多信息。
+
+### 爬虫配置 {#crawler-config}
+
+以下是基于此站点使用的示例配置:
+
+```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: '',
+ 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: '',
+ highlightPostTag: '',
+ minWordSizefor1Typo: 3,
+ minWordSizefor2Typos: 7,
+ allowTyposOnNumericTokens: false,
+ minProximity: 1,
+ ignorePlurals: true,
+ advancedSyntax: true,
+ attributeCriteriaComputedByMinProximity: true,
+ removeWordsIfNoResults: 'allOptional'
+ }
+ }
+})
+```
+
+
diff --git a/docs/zh/reference/default-theme-sidebar.md b/docs/zh/reference/default-theme-sidebar.md
new file mode 100644
index 00000000..8a001c0d
--- /dev/null
+++ b/docs/zh/reference/default-theme-sidebar.md
@@ -0,0 +1,213 @@
+# 侧边栏 {#sidebar}
+
+侧边栏是文档的主要导航块。可以在 [`themeConfig.sidebar`](./default-theme-config#sidebar) 中配置侧边栏菜单。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Guide',
+ items: [
+ { text: 'Introduction', link: '/introduction' },
+ { text: 'Getting Started', link: '/getting-started' },
+ ...
+ ]
+ }
+ ]
+ }
+}
+```
+
+## 基本用法 {#the-basics}
+
+侧边栏菜单的最简单形式是传入一个链接数组。第一级项目定义侧边栏的“部分”。它应该包含作为小标题的 `text` 和作为实际导航链接的 `items`。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ items: [
+ { text: 'Item A', link: '/item-a' },
+ { text: 'Item B', link: '/item-b' },
+ ...
+ ]
+ },
+ {
+ text: 'Section Title B',
+ items: [
+ { text: 'Item C', link: '/item-c' },
+ { text: 'Item D', link: '/item-d' },
+ ...
+ ]
+ }
+ ]
+ }
+}
+```
+
+每个 `link` 都应指定以 `/` 开头的实际文件的路径。如果在链接末尾添加斜杠,它将显示相应目录的 `index.md`。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Guide',
+ items: [
+ // 显示的是 `/guide/index.md` 页面
+ { text: 'Introduction', link: '/guide/' }
+ ]
+ }
+ ]
+ }
+}
+```
+
+可以进一步将侧边栏项目嵌入到 6 级深度,从根级别上计数。请注意,深度超过 6 级将被忽略,并且不会在侧边栏上显示。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Level 1',
+ items: [
+ {
+ text: 'Level 2',
+ items: [
+ {
+ text: 'Level 3',
+ items: [
+ ...
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+```
+
+## 多侧边栏 {#multiple-sidebars}
+
+可能会根据页面路径显示不同的侧边栏。例如,如本站点所示,可能希望在文档中创建单独的侧边栏,例如“指南”页面和“配置参考”页面。
+
+为此,首先将你的页面组织到每个所需部分的目录中:
+
+```
+.
+├─ guide/
+│ ├─ index.md
+│ ├─ one.md
+│ └─ two.md
+└─ config/
+ ├─ index.md
+ ├─ three.md
+ └─ four.md
+```
+
+然后,更新配置以定义每个部分的侧边栏。这一次,应该传递一个对象而不是数组。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: {
+ // 当用户位于 `guide` 目录时,会显示此侧边栏
+ '/guide/': [
+ {
+ text: 'Guide',
+ items: [
+ { text: 'Index', link: '/guide/' },
+ { text: 'One', link: '/guide/one' },
+ { text: 'Two', link: '/guide/two' }
+ ]
+ }
+ ],
+
+ // 当用户位于 `config` 目录时,会显示此侧边栏
+ '/config/': [
+ {
+ text: 'Config',
+ items: [
+ { text: 'Index', link: '/config/' },
+ { text: 'Three', link: '/config/three' },
+ { text: 'Four', link: '/config/four' }
+ ]
+ }
+ ]
+ }
+ }
+}
+```
+
+## 可折叠的侧边栏组 {#collapsible-sidebar-groups}
+
+通过向侧边栏组添加 `collapsed` 选项,它会显示一个切换按钮来隐藏/显示每个部分。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ collapsed: false,
+ items: [...]
+ }
+ ]
+ }
+}
+```
+
+默认情况下,所有部分都是“打开”的。如果 希望它们在初始页面加载时“关闭”,请将 `collapsed` 选项设置为 `true`。
+
+```js
+export default {
+ themeConfig: {
+ sidebar: [
+ {
+ text: 'Section Title A',
+ collapsed: true,
+ items: [...]
+ }
+ ]
+ }
+}
+```
+
+## `useSidebar`
+
+返回侧边栏相关数据。返回的对象具有以下类型:
+
+```ts
+export interface DocSidebar {
+ isOpen: Ref
+ sidebar: ComputedRef
+ sidebarGroups: ComputedRef
+ hasSidebar: ComputedRef
+ hasAside: ComputedRef
+ leftAside: ComputedRef
+ isSidebarEnabled: ComputedRef
+ open: () => void
+ close: () => void
+ toggle: () => void
+}
+```
+
+**示例:**
+
+```vue
+
+
+
+ Only show when sidebar exists
+
+```
diff --git a/docs/zh/reference/default-theme-team-page.md b/docs/zh/reference/default-theme-team-page.md
new file mode 100644
index 00000000..0ff5568e
--- /dev/null
+++ b/docs/zh/reference/default-theme-team-page.md
@@ -0,0 +1,257 @@
+
+
+# 团队页 {#team-page}
+
+如果你想介绍你的团队,你可以使用 Team components 来构建团队页面。有两种使用这些组件的方法。一种是将其嵌入文档页面,另一种是创建完整的团队页面。
+
+## 在页面中显示团队成员 {#show-team-members-in-a-page}
+
+你可以在任何页面上使用从 `vitepress/theme` 暴露出的公共组件 `` 显示团队成员。
+
+```html
+
+
+# Our Team
+
+Say hello to our awesome team.
+
+
+```
+
+以上将在卡片外观元素中显示团队成员。它应该显示类似于下面的内容。
+
+
+
+`` 组件有 2 种不同的尺寸,`small` 和 `medium`。虽然它取决于你的偏好,但通常尺寸在文档页面中使用时 `small` 应该更适合。此外,你可以为每个成员添加更多属性,例如添加“描述”或“赞助”按钮。在 [``](#vpteammembers)中了解更多信息。
+
+在文档页面中嵌入团队成员对于小型团队来说非常有用,某种情况下,完整的贡献团队可能太大了,可以引入部分成员作为文档上下文的参考。
+
+如果你有大量成员,或者只是想有更多空间来展示团队成员,请考虑[创建一个完整的团队页面](#create-a-full-team-page)。
+
+## 创建一个完整的团队页面 {#create-a-full-team-page}
+
+除了将团队成员添加到 doc 页面,你还可以创建一个完整的团队页面,类似于创建自定义[默认主题:主页](./default-theme-home-page)的方式。
+
+要创建团队页面,首先,创建一个新的 md 文件。文件名无所谓,这里我们就叫它 `team.md` 吧。在这个文件中,在 frontmatter 设置 `layout: page`,然后你可以使用 `TeamPage` 组件来组成页面结构。
+
+```html
+---
+layout: page
+---
+
+
+
+
+
+ Our Team
+
+
+ The development of VitePress is guided by an international
+ team, some of whom have chosen to be featured below.
+
+
+
+
+```
+
+创建完整的团队页面时,请记住用 `` 组件包装所有团队相关组件,以获得正确的布局结构,如间距。
+
+`` 组件添加页面标题部分。标题是 `` 标题。使用 `#title` 和 `#lead` 插槽来介绍你的团队。
+
+`` 和在 doc 页面中使用时一样。它将显示成员列表。
+
+### 添加分段以划分团队成员 {#add-sections-to-divide-team-members}
+
+你可以将“分段”添加到团队页面。例如,你可能有不同类型的团队成员,例如核心团队成员和社区合作伙伴。你可以将这些成员分成几个部分,以更好地解释每组的角色。
+
+为此,将 `` 组件添加到我们之前创建的 `team.md` 文件中。
+
+```html
+---
+layout: page
+---
+
+
+
+
+ Our Team
+ ...
+
+
+
+ Partners
+ ...
+
+
+
+
+
+```
+
+`` 组件可以有类似于 `VPTeamPageTitle` 组件的 `#title` 和 `#lead` 插槽,还有用于显示团队成员的 `#members` 插槽。
+
+请记住将 `` 组件放入 `#members` 插槽中。
+
+## ``
+
+`` 组件显示给定的成员列表。
+
+```html
+
+```
+
+```ts
+interface Props {
+ // 每个成员的大小,默认为 `medium`
+ size?: 'small' | 'medium'
+
+ // 显示的成员列表
+ members: TeamMember[]
+}
+
+interface TeamMember {
+ // 成员的头像图像
+ avatar: string
+
+ // 成员的名称
+ name: string
+
+ // 成员姓名下方的标题
+ // 例如:Developer, Software Engineer, etc.
+ title?: string
+
+ // 成员所属的组织
+ org?: string
+
+ // 组织的 URL
+ orgLink?: string
+
+ // 成员的描述
+ desc?: string
+
+ // 社交媒体链接,例如 GitHub、Twitter 等,可以在此处传入 Social Links 对象
+ // 参见: https://vitepress.dev/reference/default-theme-config.html#sociallinks
+ links?: SocialLink[]
+
+ // 成员 sponsor 页面的 URL
+ sponsor?: string
+
+ // sponsor 链接的文本,默认为 'Sponsor'
+ actionText?: string
+}
+```
+
+## ``
+
+创建完整团队页面时的根组件。它只接受一个插槽。它将设置所有传入的团队相关组件的样式。
+
+## ``
+
+添加页面的标题。最好在一开始就在 `` 下使用。它接受 `#title` 和 `#lead` 插槽。
+
+```html
+
+
+
+ Our Team
+
+
+ The development of VitePress is guided by an international
+ team, some of whom have chosen to be featured below.
+
+
+
+```
+
+## ``
+
+在团队页面中创建一个“分段”。它接受 `#title`、`#lead` 和 `#members` 插槽。你可以在 `` 中添加任意数量的分段。
+
+```html
+
+ ...
+
+ Partners
+ Lorem ipsum...
+
+
+
+
+
+```
diff --git a/docs/zh/reference/frontmatter-config.md b/docs/zh/reference/frontmatter-config.md
new file mode 100644
index 00000000..48ff8c49
--- /dev/null
+++ b/docs/zh/reference/frontmatter-config.md
@@ -0,0 +1,221 @@
+---
+outline: deep
+---
+
+# frontmatter 配置 {#frontmatter-config}
+
+frontmatter 支持基于页面的配置。在每个 markdown 文件中,可以使用 frontmatter 配置来覆盖站点级别或主题级别的配置选项。此外,还有一些配置选项只能在 frontmatter 中定义。
+
+示例用法:
+
+```md
+---
+title: Docs with VitePress
+editLink: true
+---
+```
+
+可以通过 Vue 表达式中的 `$frontmatter` 全局变量访问 frontmatter 数据:
+
+```md
+{{ $frontmatter.title }}
+```
+
+## title
+
+- 类型:`string`
+
+页面的标题。它与 [config.title](./site-config#title) 相同,并且覆盖站点级配置。
+
+```yaml
+---
+title: VitePress
+---
+```
+
+## titleTemplate
+
+- 类型:`string | boolean`
+
+标题的后缀。它与 [config.titleTemplate](./site-config#titletemplate) 相同,它会覆盖站点级别的配置。
+
+```yaml
+---
+title: VitePress
+titleTemplate: Vite & Vue powered static site generator
+---
+```
+
+## description
+
+- 类型:`string`
+
+页面的描述。它与 [config.description](./site-config#description) 相同,它会覆盖站点级别的配置。
+
+```yaml
+---
+description: VitePress
+---
+```
+
+## head
+
+- 类型:`HeadConfig[]`
+
+指定要为当前页面注入的额外 head 标签。将附加在站点级配置注入的头部标签之后。
+
+```yaml
+---
+head:
+ - - meta
+ - name: description
+ content: hello
+ - - meta
+ - name: keywords
+ content: super duper SEO
+---
+```
+
+```ts
+type HeadConfig =
+ | [string, Record]
+ | [string, Record, string]
+```
+
+## 仅默认主题 {#default-theme-only}
+
+以下 frontmatter 选项仅在使用默认主题时适用。
+
+### layout
+
+- 类型:`doc | home | page`
+- 默认值:`doc`
+
+指定页面的布局。
+
+- `doc`——它将默认文档样式应用于 markdown 内容。
+- `home`——“主页”的特殊布局。可以添加额外的选项,例如 `hero` 和 `features`,以快速创建漂亮的落地页。
+- `page`——表现类似于 `doc`,但它不对内容应用任何样式。当想创建一个完全自定义的页面时很有用。
+
+```yaml
+---
+layout: doc
+---
+```
+
+### hero
+
+当 `layout` 设置为 `home` 时,定义主页 hero 部分的内容。更多详细信息:[默认主题:主页](./default-theme-home-page)。
+
+### features
+
+定义当`layout` 设置为 `home` 时要在 features 部分中显示的项目。更多详细信息:[默认主题:主页](./default-theme-home-page)。
+
+### navbar
+
+- 类型:`boolean`
+- 默认值:`true`
+
+是否显示[导航栏](./default-theme-nav)。
+
+```yaml
+---
+navbar: false
+---
+```
+
+### sidebar
+
+- 类型:`boolean`
+- 默认值:`true`
+
+是否显示 [侧边栏](./default-theme-sidebar).
+
+```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](./default-theme-config#outline) 相同,它会覆盖站点级的配置。
+
+### lastUpdated
+
+- 类型:`boolean | Date`
+- 默认值:`true`
+
+是否在当前页面的页脚中显示[最近更新时间](./default-theme-last-updated)的文本。如果指定了日期时间,则会显示该日期时间而不是上次 git 修改的时间戳。
+
+```yaml
+---
+lastUpdated: false
+---
+```
+
+### editLink
+
+- 类型:`boolean`
+- 默认值:`true`
+
+是否在当前页的页脚显示[编辑链接](./default-theme-edit-link)。
+
+```yaml
+---
+editLink: false
+---
+```
+
+### footer
+
+- 类型:`boolean`
+- 默认值:`true`
+
+是否显示[页脚](./default-theme-footer)。
+
+```yaml
+---
+footer: false
+---
+```
+
+### pageClass
+
+- 类型:`string`
+
+将额外的类名称添加到特定页面。
+
+```yaml
+---
+pageClass: custom-page-class
+---
+```
+
+然后可以在 `.vitepress/theme/custom.css` 文件中自定义该特定页面的样式:
+
+```css
+.custom-page-class {
+ /* 特定页面的样式 */
+}
+```
diff --git a/docs/zh/reference/runtime-api.md b/docs/zh/reference/runtime-api.md
new file mode 100644
index 00000000..6bd232f7
--- /dev/null
+++ b/docs/zh/reference/runtime-api.md
@@ -0,0 +1,164 @@
+# 运行时 API {#runtime-api}
+
+VitePress 提供了几个内置的 API 来让你访问应用程序数据。VitePress 还附带了一些可以在全局范围内使用的内置组件。
+
+辅助函数可从 `vitepress` 全局导入,通常用于自定义主题 Vue 组件。但是,它们也可以在 `.md` 页面内使用,因为 markdown 文件被编译成 Vue [单文件组件](https://vuejs.org/guide/scaling-up/sfc.html)。
+
+以 `use*` 开头的方法表示它是一个 [Vue 3 Composition API](https://vuejs.org/guide/introduction.html#composition-api) 函数(“Composable(可组合)”),只能在 `setup()` 或 `
+
+
+ {{ theme.footer.copyright }}
+
+```
+
+## `useRoute`
+
+返回具有以下类型的当前路由对象:
+
+```ts
+interface Route {
+ path: string
+ data: PageData
+ component: Component | null
+}
+```
+
+## `useRouter`
+
+返回 VitePress 路由实例,以便可以以编程方式导航到另一个页面。
+
+```ts
+interface Router {
+ /**
+ * 当前路由
+ */
+ route: Route
+ /**
+ * 导航到新的 URL
+ */
+ go: (to?: string) => Promise
+ /**
+ * 在路由更改前调用。返回 `false` 表示取消导航
+ */
+ onBeforeRouteChange?: (to: string) => Awaitable
+ /**
+ * 在页面组件加载前(history 状态更新后)调用。返回 `false` 表示取消导航
+ */
+ onBeforePageLoad?: (to: string) => Awaitable
+ /**
+ * 在路由更改后调用
+ */
+ onAfterRouteChanged?: (to: string) => Awaitable
+}
+```
+
+## `withBase`
+
+- **Type**: `(path: string) => string`
+
+将配置的 [`base`](./site-config#base) 追加到给定的 URL 路径。另请参阅 [Base URL](../guide/asset-handling#base-url)。
+
+## ``
+
+`` 组件显示渲染的 markdown 内容。在[创建自己的主题时](../guide/custom-theme)很有用。
+
+```vue
+
+ Custom Layout!
+
+
+```
+
+## ``
+
+`` 组件仅在客户端渲染其插槽。
+
+由于 VitePress 应用程序在生成静态构建时是在 Node.js 中服务器渲染的,因此任何 Vue 使用都必须符合通用代码要求。简而言之,确保仅在 beforeMount 或 mounted 钩子中访问 Browser/DOM API。
+
+如果正在使用或演示对 SSR 不友好的组件 (例如,包含自定义指令),可以将它们包装在 `ClientOnly` 组件中。
+
+```vue-html
+
+
+
+```
+
+- 相关文档:[SSR 兼容性](../guide/ssr-compat)
+
+## `$frontmatter`
+
+在 Vue 表达式中直接访问当前页面的 [frontmatter](../guide/frontmatter) 数据。
+
+```md
+---
+title: Hello
+---
+
+# {{ $frontmatter.title }}
+```
+
+## `$params`
+
+在 Vue 表达式中直接访问当前页面的[动态路由参数](../guide/routing#dynamic-routes)。
+
+```md
+- package name: {{ $params.pkg }}
+- version: {{ $params.version }}
+```
diff --git a/docs/zh/reference/site-config.md b/docs/zh/reference/site-config.md
new file mode 100644
index 00000000..fd5c2c4f
--- /dev/null
+++ b/docs/zh/reference/site-config.md
@@ -0,0 +1,695 @@
+---
+outline: deep
+---
+
+# 站点配置 {#site-config}
+
+站点配置可以定义站点的全局设置。应用配置选项适用于每个 VitePress 站点,无论它使用什么主题。例如根目录或站点的标题。
+
+## 概览 {#overview}
+
+### 配置解析 {#config-resolution}
+
+配置文件总是从 `/.vitepress/config.[ext]` 解析,其中 `` 是 VitePress [项目根目录](../guide/routing#root-and-source-directory),`[ext]` 是支持的文件扩展名之一。开箱即用地支持 TypeScript。支持的扩展名包括 `.js`、`.ts`、`.mjs` 和 `.mts`。
+
+建议在配置文件中使用 ES 模块语法。配置文件应该默认导出一个对象:
+
+```ts
+export default {
+ // 应用级配置选项
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+ ...
+}
+```
+
+:::details 异步的动态配置
+
+如果需要动态生成配置,也可以默认导出一个函数,例如:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default async () => defineConfig({
+ const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
+
+ return {
+ // 应用级配置选项
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+
+ // 主题级别配置选项
+ themeConfig: {
+ sidebar: [
+ ...posts.map((post) => ({
+ text: post.name,
+ link: `/posts/${post.name}`
+ }))
+ ]
+ }
+ }
+})
+```
+
+也可以在最外层使用 `await`。例如:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
+
+export default defineConfig({
+ // 应用级配置选项
+ lang: 'en-US',
+ title: 'VitePress',
+ description: 'Vite & Vue powered static site generator.',
+
+ // 主题级别配置选项
+ themeConfig: {
+ sidebar: [
+ ...posts.map((post) => ({
+ text: post.name,
+ link: `/posts/${post.name}`
+ }))
+ ]
+ }
+})
+```
+
+:::
+
+### 配置智能提示 {#config-intellisense}
+
+使用 `defineConfig` 辅助函数将为配置选项提供 TypeScript 支持的智能提示。假设 IDE 支持它,那么智能提示在 JavaScript 和 TypeScript 中都将触发。
+
+```js
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ // ...
+})
+```
+
+### 主题类型提示 {#typed-theme-config}
+
+默认情况下,`defineConfig` 辅助函数期望默认主题的主题配置数据类型:
+
+```ts
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ themeConfig: {
+ // 类型为 `DefaultTheme.Config`
+ }
+})
+```
+
+如果使用自定义主题并希望对主题配置进行类型检查,则需要改用 `defineConfigWithTheme`,并通过通用参数传递自定义主题的配置类型:
+
+```ts
+import { defineConfigWithTheme } from 'vitepress'
+import type { ThemeConfig } from 'your-theme'
+
+export default defineConfigWithTheme({
+ themeConfig: {
+ // 类型为 `ThemeConfig`
+ }
+})
+```
+
+### Vite、Vue 和 Markdown 配置
+
+- **Vite**
+
+ 可以使用 VitePress 配置中的 [vite](#vite) 选项配置底层 Vite 实例。无需创建单独的 Vite 配置文件。
+
+- **Vue**
+
+ VitePress 已经包含 Vite 的官方 Vue 插件([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))。可以配置 VitePress 中的 [vue](#vue) 选项。
+
+- **Markdown**
+
+ 可以使用 VitePress 配置中的 [markdown](#markdown) 选项配置底层的 [Markdown-It](https://github.com/markdown-it/markdown-it) 实例。
+
+## 站点元数据 {#site-metadata}
+
+### title
+
+- 类型:`string`
+- 默认值: `VitePress`
+- 每个页面可以通过 [frontmatter](./frontmatter-config#title) 覆盖
+
+站点的标题。使用默认主题时,这将显示在导航栏中。
+
+它还将用作所有单独页面标题的默认后缀,除非定义了 [`titleTemplate`](#titletemplate)。单个页面的最终标题将是其第一个 `` 标题的文本内容加上的全局 `title`。例如使用以下配置和页面内容:
+
+```ts
+export default {
+ title: 'My Awesome Site'
+}
+```
+
+```md
+# Hello
+```
+
+页面标题就是 `Hello | My Awesome Site`.
+
+### titleTemplate
+
+- 类型:`string | boolean`
+- 每个页面可以通过 [frontmatter](./frontmatter-config#titletemplate) 覆盖
+
+允许自定义每个页面的标题后缀或整个标题。例如:
+
+```ts
+export default {
+ title: 'My Awesome Site',
+ titleTemplate: 'Custom Suffix'
+}
+```
+
+```md
+# Hello
+```
+
+页面标题就是 `Hello | Custom Suffix`.
+
+要完全自定义标题的呈现方式,可以在 `titleTemplate` 中使用 `:title` 标识符:
+
+```ts
+export default {
+ titleTemplate: ':title - Custom Suffix'
+}
+```
+
+这里的 `:title` 将替换为从页面的第一个 `` 标题推断出的文本。上一个示例页面的标题将是 `Hello - Custom Suffix`。
+
+该选项可以设置为 `false` 以禁用标题后缀。
+
+### description
+
+- 类型:`string`
+- 默认值: `A VitePress site`
+- 每个页面可以通过 [frontmatter](./frontmatter-config#description) 覆盖
+
+站点的描述。这将呈现为页面 HTML 中的 `` 标签。
+
+```ts
+export default {
+ description: 'A VitePress site'
+}
+```
+
+### head
+
+- 类型:`HeadConfig[]`
+- 默认值: `[]`
+- 每个页面可以通过 [frontmatter](./frontmatter-config#head) 添加
+
+要在页面 HTML 的 `` 标记中呈现的其他元素。用户添加的标签在结束 `head` 标签之前呈现,在 VitePress 标签之后。
+
+```ts
+type HeadConfig =
+ | [string, Record]
+ | [string, Record, string]
+```
+
+#### 示例:添加一个图标 {#example-adding-a-favicon}
+
+```ts
+export default {
+ head: [['link', { rel: 'icon', href: '/favicon.ico' }]]
+} // 将 favicon.ico 放在公共目录中,如果设置了 base,则使用 /base/favicon.ico
+
+/* 渲染成:
+
+*/
+```
+
+#### 示例:添加谷歌字体 {#example-adding-google-fonts}
+
+```ts
+export default {
+ head: [
+ [
+ 'link',
+ { rel: 'preconnect', href: 'https://fonts.googleapis.com' }
+ ],
+ [
+ 'link',
+ { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }
+ ],
+ [
+ 'link',
+ { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' }
+ ]
+ ]
+}
+
+/* 渲染成:
+
+
+
+*/
+```
+
+#### 示例:添加一个 serviceWorker {#example-registering-a-service-worker}
+
+```ts
+export default {
+ head: [
+ [
+ 'script',
+ { id: 'register-sw' },
+ `;(() => {
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('/sw.js')
+ }
+ })()`
+ ]
+ ]
+}
+
+/* 渲染成:
+
+*/
+```
+
+#### 示例:使用谷歌分析 {#example-using-google-analytics}
+
+```ts
+export default {
+ head: [
+ [
+ 'script',
+ { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' }
+ ],
+ [
+ 'script',
+ {},
+ `window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+ gtag('js', new Date());
+ gtag('config', 'TAG_ID');`
+ ]
+ ]
+}
+
+/* 渲染成:
+
+
+*/
+```
+
+### lang
+
+- 类型:`string`
+- 默认值: `en-US`
+
+站点的 lang 属性。这将呈现为页面 HTML 中的 `` 标签。
+
+```ts
+export default {
+ lang: 'en-US'
+}
+```
+
+### base
+
+- 类型:`string`
+- 默认值: `/`
+
+站点将部署到的 base URL。如果计划在子路径(例如 GitHub 页面)下部署站点,则需要设置此项。如果计划将站点部署到 `https://foo.github.io/bar/`,那么应该将 `base` 设置为 `“/bar/”`。它应该始终以 `/`开头和结尾。
+
+base 会自动添加到其他选项中以 `/` 开头的所有 URL 前面,因此只需指定一次。
+
+```ts
+export default {
+ base: '/base/'
+}
+```
+
+## 路由 {#routing}
+
+### cleanUrls
+
+- 类型:`boolean`
+- 默认值: `false`
+
+当设置为 `true` 时,VitePress 将从 URL 中删除 `.html` 后缀。另请参阅[生成简洁的 URL](../guide/routing#generating-clean-url)。
+
+::: warning 需要服务器支持
+要启用此功能,可能需要在托管平台上进行额外配置。要使其正常工作,服务器必须能够在**不重定向的情况下**访问 `/foo` 时提供 `/foo.html`。
+:::
+
+### rewrites
+
+- 类型:`Record`
+
+自定义目录 <-> URL 映射。详细信息请参阅[路由:路由重写](../guide/routing#route-rewrites)。
+
+```ts
+export default {
+ rewrites: {
+ 'source/:page': 'destination/:page'
+ }
+}
+```
+
+## 构建 {#build}
+
+### srcDir
+
+- 类型:`string`
+- 默认值: `.`
+
+markdown 页面的目录,相对于项目根目录。另请参阅[根目录和源目录](../guide/routing#root-and-source-directory)。
+
+```ts
+export default {
+ srcDir: './src'
+}
+```
+
+### srcExclude
+
+- 类型:`string`
+- 默认值: `undefined`
+
+用于匹配应作为源内容输出的 markdown 文件的 [全局模式](https://github.com/mrmlnc/fast-glob#pattern-syntax)。
+
+```ts
+export default {
+ srcExclude: ['**/README.md', '**/TODO.md']
+}
+```
+
+### outDir
+
+- 类型:`string`
+- 默认值: `./.vitepress/dist`
+
+项目的构建输出位置,相对于[项目根目录](../guide/routing#root-and-source-directory)。
+
+```ts
+export default {
+ outDir: '../public'
+}
+```
+
+### assetsDir
+
+- 类型:`string`
+- 默认值: `assets`
+
+指定放置生成的静态资源的目录。该路径应位于 [`outDir`](#outdir) 内,并相对于它进行解析。
+
+```ts
+export default {
+ assetsDir: 'static'
+}
+```
+
+### cacheDir
+
+- 类型:`string`
+- 默认值: `./.vitepress/cache`
+
+缓存文件的目录,相对于[项目根目录](../guide/routing#root-and-source-directory)。另请参阅:[cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)。
+
+```ts
+export default {
+ cacheDir: './.vitepress/.vite'
+}
+```
+
+### ignoreDeadLinks
+
+- 类型:`boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
+- 默认值: `false`
+
+当设置为 `true` 时,VitePress 不会因为死链而导致构建失败。
+
+当设置为 `'localhostLinks'` ,出现死链时构建将失败,但不会检查 `localhost` 链接。
+
+```ts
+export default {
+ ignoreDeadLinks: true
+}
+```
+
+它也可以是一组精确的 url 字符串、正则表达式模式或自定义过滤函数。
+
+```ts
+export default {
+ ignoreDeadLinks: [
+ // 忽略精确网址 "/playground"
+ '/playground',
+ // 忽略所有 localhost 链接
+ /^https?:\/\/localhost/,
+ // 忽略所有包含 "/repl/" 的链接
+ /\/repl\//,
+ // 自定义函数,忽略所有包含 "ignore "的链接
+ (url) => {
+ return url.toLowerCase().includes('ignore')
+ }
+ ]
+}
+```
+
+### mpa
+
+- 类型:`boolean`
+- 默认值: `false`
+
+设置为 `true` 时,生产应用程序将在 [MPA 模式](../guide/mpa-mode)下构建。MPA 模式默认提供 零 JavaScript 支持,代价是禁用客户端导航,并且需要明确选择加入才能进行交互。
+
+## 主题 {#theming}
+
+### appearance
+
+- 类型:`boolean | 'dark' | 'force-dark' | import('@vueuse/core').UseDarkOptions`
+- 默认值: `true`
+
+是否启用深色模式(通过将 `.dark` 类添加到 `` 元素)。
+
+- 如果该选项设置为 `true`,则默认主题将由用户的首选配色方案决定。
+- 如果该选项设置为 `dark`,则默认情况下主题将是深色的,除非用户手动切换它。
+- 如果该选项设置为 `false`,用户将无法切换主题。
+
+此选项注入一个内联脚本,使用 `vitepress-theme-appearance` key 从本地存储恢复用户设置。这确保在呈现页面之前应用 `.dark` 类以避免闪烁。
+
+`appearance.initialValue` 只能是 `'dark' | undefined`。 不支持 Refs 或 getters。
+
+### lastUpdated
+
+- 类型:`boolean`
+- 默认值: `false`
+
+是否使用 Git 获取每个页面的最后更新时间戳。时间戳将包含在每个页面的页面数据中,可通过 [`useData`](./runtime-api#usedata) 访问。
+
+使用默认主题时,启用此选项将显示每个页面的最后更新时间。可以通过 [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 选项自定义文本。
+
+## 自定义 {#customization}
+
+### markdown
+
+- 类型:`MarkdownOption`
+
+配置 Markdown 解析器选项。VitePress 使用 [Markdown-it](https://github.com/markdown-it/markdown-it) 作为解析器,使用[Shikiji](https://github.com/antfu/shikiji) ([Shiki](https://shiki.matsu.io/) 的改进版本) 来高亮不同语言语法。在此选项中,可以传递各种 Markdown 相关选项以满足的需要。
+
+```js
+export default {
+ markdown: {...}
+}
+```
+
+查看[类型声明和 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) 以获得所有可配置的选项。
+
+### vite
+
+- 类型:`import('vite').UserConfig`
+
+将原始 [Vite 配置](https://vitejs.dev/config/)传递给内部 Vite 开发服务器 / bundler。
+
+```js
+export default {
+ vite: {
+ // Vite 配置选项
+ }
+}
+```
+
+### vue
+
+- 类型:`import('@vitejs/plugin-vue').Options`
+
+将原始的 [@vitejs/plugin-vue 选项](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)传递给内部插件实例。
+
+```js
+export default {
+ vue: {
+ // @vitejs/plugin-vue 选项
+ }
+}
+```
+
+## 构建钩子 {#build-hooks}
+
+VitePress 构建钩子允许向站点添加新功能和行为:
+
+- Sitemap
+- Search Indexing
+- PWA
+- Teleport
+
+### buildEnd
+
+- 类型:`(siteConfig: SiteConfig) => Awaitable`
+
+`buildEnd` 是一个构建 CLI 钩子,它将在构建(SSG)完成后但在 VitePress CLI 进程退出之前运行。
+
+```ts
+export default {
+ async buildEnd(siteConfig) {
+ // ...
+ }
+}
+```
+
+### postRender
+
+- 类型:`(context: SSGContext) => Awaitable`
+
+ `postRender` 是一个构建钩子,在 SSG 渲染完成时调用。它将允许在 SSG 期间处理传递的内容。
+
+```ts
+export default {
+ async postRender(context) {
+ // ...
+ }
+}
+```
+
+```ts
+interface SSGContext {
+ content: string
+ teleports?: Record
+ [key: string]: any
+}
+```
+
+### transformHead
+
+- 类型:`(context: TransformContext) => Awaitable`
+
+`transformHead` 是一个构建钩子,用于在生成每个页面之前转换 head。它将允许添加无法静态添加到 VitePress 配置中的 head entries。只需要返回额外的 entries,它们将自动与现有 entries 合并。
+
+::: warning
+不要改变 `context` 中的任何东西。
+:::
+
+```ts
+export default {
+ async transformHead(context) {
+ // ...
+ }
+}
+```
+
+```ts
+interface TransformContext {
+ page: string // 例如 index.md (相对于 srcDir)
+ assets: string[] // 所有非 js/css 资源均作为完全解析的公共 URL
+ siteConfig: SiteConfig
+ siteData: SiteData
+ pageData: PageData
+ title: string
+ description: string
+ head: HeadConfig[]
+ content: string
+}
+```
+
+请注意,仅在静态生成站点时才会调用此挂钩。在开发期间不会调用它。如果需要在开发期间添加动态头条目,可以使用 [`transformPageData`](#transformpagedata) 钩子来替代:
+
+```ts
+export default {
+ transformPageData(pageData) {
+ pageData.frontmatter.head ??= []
+ pageData.frontmatter.head.push([
+ 'meta',
+ {
+ name: 'og:title',
+ content:
+ pageData.frontmatter.layout === 'home'
+ ? `VitePress`
+ : `${pageData.title} | VitePress`
+ }
+ ])
+ }
+}
+```
+
+### transformHtml
+
+- 类型:`(code: string, id: string, context: TransformContext) => Awaitable`
+
+`transformHtml` 是一个构建钩子,用于在保存到磁盘之前转换每个页面的内容。
+
+::: warning
+不要改变 `context` 中的任何东西。另外,修改 html 内容可能会导致运行时出现激活问题。
+:::
+
+```ts
+export default {
+ async transformHtml(code, id, context) {
+ // ...
+ }
+}
+```
+
+### transformPageData
+
+- 类型:`(pageData: PageData, context: TransformPageContext) => Awaitable | { [key: string]: any } | void>`
+
+`transformPageData` 是一个钩子,用于转换每个页面的 `pageData`。可以直接改变 `pageData` 或返回将合并到 `PageData` 中的更改值。
+
+::: warning
+不要改变 `context` 中的任何东西。请注意,这可能会影响开发服务器的性能,特别是当在钩子中有一些网络请求或大量计算(例如生成图像)时。可以通过判断 `process.env.NODE_ENV === 'production'` 匹配符合条件的情况。
+:::
+
+```ts
+export default {
+ async transformPageData(pageData, { siteConfig }) {
+ pageData.contributors = await getPageContributors(pageData.relativePath)
+ }
+
+ // 或返回要合并的数据
+ async transformPageData(pageData, { siteConfig }) {
+ return {
+ contributors: await getPageContributors(pageData.relativePath)
+ }
+ }
+}
+```
+
+```ts
+interface TransformPageContext {
+ siteConfig: SiteConfig
+}
+```
diff --git a/package.json b/package.json
index 7c7f48de..cdb3e00e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vitepress",
- "version": "1.0.0-rc.33",
+ "version": "1.0.0-rc.34",
"description": "Vite & Vue powered static site generator",
"type": "module",
"packageManager": "pnpm@8.13.1",
@@ -100,11 +100,10 @@
"focus-trap": "^7.5.4",
"mark.js": "8.11.1",
"minisearch": "^6.3.0",
- "mrmime": "^2.0.0",
"rpc-magic-proxy": "0.0.0-beta.1",
- "shikiji": "^0.9.15",
- "shikiji-core": "^0.9.15",
- "shikiji-transformers": "^0.9.15",
+ "shikiji": "^0.9.16",
+ "shikiji-core": "^0.9.16",
+ "shikiji-transformers": "^0.9.16",
"vite": "^5.0.10",
"vue": "^3.4.3"
},
@@ -198,7 +197,7 @@
"sitemap": "^7.1.1",
"supports-color": "^9.4.0",
"typescript": "^5.3.3",
- "vitest": "^1.1.0",
+ "vitest": "^1.1.1",
"vue-tsc": "^1.8.27",
"wait-on": "^7.2.0"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9213f045..f771e798 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -41,21 +41,18 @@ importers:
minisearch:
specifier: ^6.3.0
version: 6.3.0
- mrmime:
- specifier: ^2.0.0
- version: 2.0.0
rpc-magic-proxy:
- specifier: 0.0.0-beta.1
- version: 0.0.0-beta.1
+ specifier: 0.0.0-beta.3
+ version: 0.0.0-beta.3
shikiji:
- specifier: ^0.9.15
- version: 0.9.15
+ specifier: ^0.9.16
+ version: 0.9.16
shikiji-core:
- specifier: ^0.9.15
- version: 0.9.15
+ specifier: ^0.9.16
+ version: 0.9.16
shikiji-transformers:
- specifier: ^0.9.15
- version: 0.9.15
+ specifier: ^0.9.16
+ version: 0.9.16
vite:
specifier: ^5.0.10
version: 5.0.10(@types/node@20.10.6)
@@ -295,8 +292,8 @@ importers:
specifier: ^5.3.3
version: 5.3.3
vitest:
- specifier: ^1.1.0
- version: 1.1.0(@types/node@20.10.6)(supports-color@9.4.0)
+ specifier: ^1.1.1
+ version: 1.1.1(@types/node@20.10.6)(supports-color@9.4.0)
vue-tsc:
specifier: ^1.8.27
version: 1.8.27(typescript@5.3.3)
@@ -1317,38 +1314,38 @@ packages:
vue: 3.4.3(typescript@5.3.3)
dev: false
- /@vitest/expect@1.1.0:
- resolution: {integrity: sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==}
+ /@vitest/expect@1.1.1:
+ resolution: {integrity: sha512-Qpw01C2Hyb3085jBkOJLQ7HRX0Ncnh2qV4p+xWmmhcIUlMykUF69zsnZ1vPmAjZpomw9+5tWEGOQ0GTfR8U+kA==}
dependencies:
- '@vitest/spy': 1.1.0
- '@vitest/utils': 1.1.0
+ '@vitest/spy': 1.1.1
+ '@vitest/utils': 1.1.1
chai: 4.3.10
dev: true
- /@vitest/runner@1.1.0:
- resolution: {integrity: sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==}
+ /@vitest/runner@1.1.1:
+ resolution: {integrity: sha512-8HokyJo1SnSi3uPFKfWm/Oq1qDwLC4QDcVsqpXIXwsRPAg3gIDh8EbZ1ri8cmQkBxdOu62aOF9B4xcqJhvt4xQ==}
dependencies:
- '@vitest/utils': 1.1.0
+ '@vitest/utils': 1.1.1
p-limit: 5.0.0
pathe: 1.1.1
dev: true
- /@vitest/snapshot@1.1.0:
- resolution: {integrity: sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==}
+ /@vitest/snapshot@1.1.1:
+ resolution: {integrity: sha512-WnMHjv4VdHLbFGgCdVVvyRkRPnOKN75JJg+LLTdr6ah7YnL75W+7CTIMdzPEPzaDxA8r5yvSVlc1d8lH3yE28w==}
dependencies:
magic-string: 0.30.5
pathe: 1.1.1
pretty-format: 29.7.0
dev: true
- /@vitest/spy@1.1.0:
- resolution: {integrity: sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==}
+ /@vitest/spy@1.1.1:
+ resolution: {integrity: sha512-hDU2KkOTfFp4WFFPWwHFauddwcKuGQ7gF6Un/ZZkCogoAiTMN7/7YKvUDbywPZZ754iCQGjdUmXN3t4k0jm1IQ==}
dependencies:
tinyspy: 2.2.0
dev: true
- /@vitest/utils@1.1.0:
- resolution: {integrity: sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==}
+ /@vitest/utils@1.1.1:
+ resolution: {integrity: sha512-E9LedH093vST/JuBSyHLFMpxJKW3dLhe/flUSPFedoyj4wKiFX7Jm8gYLtOIiin59dgrssfmFv0BJ1u8P/LC/A==}
dependencies:
diff-sequences: 29.6.3
loupe: 2.3.7
@@ -1701,7 +1698,7 @@ packages:
/axios@1.6.3(debug@4.3.4):
resolution: {integrity: sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==}
dependencies:
- follow-redirects: 1.15.3(debug@4.3.4)
+ follow-redirects: 1.15.4(debug@4.3.4)
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
@@ -2450,8 +2447,8 @@ packages:
tabbable: 6.2.0
dev: false
- /follow-redirects@1.15.3(debug@4.3.4):
- resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
+ /follow-redirects@1.15.4(debug@4.3.4):
+ resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
@@ -3355,6 +3352,7 @@ packages:
/mrmime@2.0.0:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'}
+ dev: true
/ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
@@ -3893,9 +3891,9 @@ packages:
'@rollup/rollup-win32-x64-msvc': 4.9.2
fsevents: 2.3.3
- /rpc-magic-proxy@0.0.0-beta.1:
- resolution: {integrity: sha512-Vqf8sflbh/Xpw6pfFAV+sd4iY3yJYN/vhh0WdTMTVGg5Lva3gwumPfSA4X5RFjSulLcjxusOUrlXp9vJ8ycgKQ==}
- dev: false
+ /rpc-magic-proxy@0.0.0-beta.3:
+ resolution: {integrity: sha512-k1hVDnaX4TBxVWpW6tRoc3qCyuuJ8luOeK4ArqkFJKinBa0yVnZzgYVtvLzC9iWnVzNKIQNNsxkth445nKWL1Q==}
+ dev: true
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -4003,20 +4001,20 @@ packages:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
dev: true
- /shikiji-core@0.9.15:
- resolution: {integrity: sha512-7hqIcUKS15OMs/61Qp2GvO1fSajBB36bDqi8vexIg5kp80V6v6SGtBrlq+nLlo7erMG2d1kvIuTIq1bwKI6fEg==}
+ /shikiji-core@0.9.16:
+ resolution: {integrity: sha512-eJIK8/IpzvAGnbckCE2Qf/fOSfpjVLSosUfI3pQAnbphGXagEqiRcT/gyVtL4llqmBh0nexqRdJKMFZF3A6ayw==}
dev: false
- /shikiji-transformers@0.9.15:
- resolution: {integrity: sha512-k0sQ6tX26/cdb8QV9CCwwr7QjRp6/AVP9C0oNIXNld3of+xCrpf74kD74piybG6vMfzBoHGsz/s60RVBJOUaYQ==}
+ /shikiji-transformers@0.9.16:
+ resolution: {integrity: sha512-DcvhYtLc3Xtme070vgyyeHX0XrNK0zHrKIiPk8wcptFbFUuS65qYDd/UFl68+R8KhdoSFTM9EXlBa9MhrGlbaw==}
dependencies:
- shikiji: 0.9.15
+ shikiji: 0.9.16
dev: false
- /shikiji@0.9.15:
- resolution: {integrity: sha512-+inN4cN+nY7b0uCPOiqFHAk+cn2DEdM3AIQgPhAV7QKqhww/o7OGS5xvLh3SNnjke9C/HispALqGOQGYHVq7KQ==}
+ /shikiji@0.9.16:
+ resolution: {integrity: sha512-QeSwiW88gHke9deQ5Av1f6CEVPGW/riRMPT3vMDGPnASCOhBZK4TYk5ZRoa2qYLncPZS5kXKwcggccQvg3+U7Q==}
dependencies:
- shikiji-core: 0.9.15
+ shikiji-core: 0.9.16
dev: false
/side-channel@1.0.4:
@@ -4453,8 +4451,8 @@ packages:
engines: {node: '>= 0.8'}
dev: true
- /vite-node@1.1.0(@types/node@20.10.6)(supports-color@9.4.0):
- resolution: {integrity: sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==}
+ /vite-node@1.1.1(@types/node@20.10.6)(supports-color@9.4.0):
+ resolution: {integrity: sha512-2bGE5w4jvym5v8llF6Gu1oBrmImoNSs4WmRVcavnG2me6+8UQntTqLiAMFyiAobp+ZXhj5ZFhI7SmLiFr/jrow==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
dependencies:
@@ -4509,8 +4507,8 @@ packages:
optionalDependencies:
fsevents: 2.3.3
- /vitest@1.1.0(@types/node@20.10.6)(supports-color@9.4.0):
- resolution: {integrity: sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==}
+ /vitest@1.1.1(@types/node@20.10.6)(supports-color@9.4.0):
+ resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
@@ -4535,11 +4533,11 @@ packages:
optional: true
dependencies:
'@types/node': 20.10.6
- '@vitest/expect': 1.1.0
- '@vitest/runner': 1.1.0
- '@vitest/snapshot': 1.1.0
- '@vitest/spy': 1.1.0
- '@vitest/utils': 1.1.0
+ '@vitest/expect': 1.1.1
+ '@vitest/runner': 1.1.1
+ '@vitest/snapshot': 1.1.1
+ '@vitest/spy': 1.1.1
+ '@vitest/utils': 1.1.1
acorn-walk: 8.3.1
cac: 6.7.14
chai: 4.3.10
@@ -4554,7 +4552,7 @@ packages:
tinybench: 2.5.1
tinypool: 0.8.1
vite: 5.0.10(@types/node@20.10.6)
- vite-node: 1.1.0(@types/node@20.10.6)(supports-color@9.4.0)
+ vite-node: 1.1.1(@types/node@20.10.6)(supports-color@9.4.0)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
diff --git a/src/client/app/index.ts b/src/client/app/index.ts
index 023b93ae..a7db0c23 100644
--- a/src/client/app/index.ts
+++ b/src/client/app/index.ts
@@ -135,7 +135,11 @@ function newRouter(): Router {
pageFilePath = pageFilePath.replace(/\.js$/, '.lean.js')
}
- pageModule = import(/*@vite-ignore*/ pageFilePath)
+ if (import.meta.env.SSR) {
+ pageModule = import(/*@vite-ignore*/ pageFilePath + '?t=' + Date.now())
+ } else {
+ pageModule = import(/*@vite-ignore*/ pageFilePath)
+ }
}
if (inBrowser) {
diff --git a/src/client/app/router.ts b/src/client/app/router.ts
index 3a7d8cb5..02d98944 100644
--- a/src/client/app/router.ts
+++ b/src/client/app/router.ts
@@ -1,7 +1,6 @@
import { reactive, inject, markRaw, nextTick, readonly } from 'vue'
import type { Component, InjectionKey } from 'vue'
-import { lookup } from 'mrmime'
-import { notFoundPageData } from '../shared'
+import { notFoundPageData, treatAsHtml } from '../shared'
import type { PageData, PageDataPayload, Awaitable } from '../shared'
import { inBrowser, withBase } from './utils'
import { siteDataRef } from './data'
@@ -182,8 +181,7 @@ export function createRouter(
link.baseURI
)
const currentUrl = window.location
- const mimeType = lookup(pathname)
- // only intercept inbound links
+ // only intercept inbound html links
if (
!e.ctrlKey &&
!e.shiftKey &&
@@ -191,8 +189,7 @@ export function createRouter(
!e.metaKey &&
!target &&
origin === currentUrl.origin &&
- // intercept only html and unknown types (assume html)
- (!mimeType || mimeType === 'text/html')
+ treatAsHtml(pathname)
) {
e.preventDefault()
if (
diff --git a/src/client/theme-default/components/VPBadge.vue b/src/client/theme-default/components/VPBadge.vue
index b9c14aa9..1d5c1678 100644
--- a/src/client/theme-default/components/VPBadge.vue
+++ b/src/client/theme-default/components/VPBadge.vue
@@ -14,7 +14,7 @@ withDefaults(defineProps(), {
-
diff --git a/src/client/theme-default/components/VPDocOutlineDropdown.vue b/src/client/theme-default/components/VPDocOutlineDropdown.vue
deleted file mode 100644
index e6009402..00000000
--- a/src/client/theme-default/components/VPDocOutlineDropdown.vue
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/client/theme-default/components/VPDocOutlineItem.vue b/src/client/theme-default/components/VPDocOutlineItem.vue
index 4ba55b99..89ea9710 100644
--- a/src/client/theme-default/components/VPDocOutlineItem.vue
+++ b/src/client/theme-default/components/VPDocOutlineItem.vue
@@ -14,7 +14,7 @@ function onClick({ target: el }: Event) {
-
+
-
{{ title }}
@@ -31,18 +31,20 @@ function onClick({ target: el }: Event) {
}
.nested {
+ padding-right: 16px;
padding-left: 16px;
}
.outline-link {
display: block;
- line-height: 28px;
+ line-height: 32px;
+ font-size: 14px;
+ font-weight: 400;
color: var(--vp-c-text-2);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: color 0.5s;
- font-weight: 400;
}
.outline-link:hover,
diff --git a/src/client/theme-default/components/VPLocalNav.vue b/src/client/theme-default/components/VPLocalNav.vue
index 0ef64c18..5491b94c 100644
--- a/src/client/theme-default/components/VPLocalNav.vue
+++ b/src/client/theme-default/components/VPLocalNav.vue
@@ -1,9 +1,10 @@
@@ -77,10 +85,6 @@ const classes = computed(() => {
/*rtl:ignore*/
left: 0;
z-index: var(--vp-z-index-local-nav);
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-top: 1px solid var(--vp-c-gutter);
border-bottom: 1px solid var(--vp-c-gutter);
padding-top: var(--vp-layout-top-height, 0px);
width: 100%;
@@ -91,16 +95,38 @@ const classes = computed(() => {
position: fixed;
}
-.VPLocalNav.reached-top {
- border-top-color: transparent;
+@media (min-width: 960px) {
+ .VPLocalNav {
+ top: var(--vp-nav-height);
+ }
+
+ .VPLocalNav.has-sidebar {
+ padding-left: var(--vp-sidebar-width);
+ }
+
+ .VPLocalNav.empty {
+ display: none;
+ }
}
-@media (min-width: 960px) {
+@media (min-width: 1280px) {
.VPLocalNav {
display: none;
}
}
+@media (min-width: 1440px) {
+ .VPLocalNav.has-sidebar {
+ padding-left: calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width));
+ }
+}
+
+.container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
.menu {
display: flex;
align-items: center;
@@ -123,6 +149,12 @@ const classes = computed(() => {
}
}
+@media (min-width: 960px) {
+ .menu {
+ display: none;
+ }
+}
+
.menu-icon {
margin-right: 8px;
width: 16px;
diff --git a/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue b/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
index d31e9f3f..2e8e310e 100644
--- a/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
+++ b/src/client/theme-default/components/VPLocalNavOutlineDropdown.vue
@@ -1,4 +1,5 @@
-
+
-