mirror of https://github.com/vuejs/vitepress
parent
3dbbd80ec3
commit
8227cde90b
@ -1,94 +0,0 @@
|
||||
# 运行时 API 参考 {#runtime-api-reference}
|
||||
|
||||
VitePress 提供了几个内置 API 来获取数据。VitePress 还提供了一些可以全局使用的内置组件。
|
||||
|
||||
可以从 `vitepress` 全局引入辅助函数,通常用于自定义主题 Vue 组件。当然,它们也可以在 .md 页面中使用,因为 Markdown 文件会被编译成 Vue 单文件组件。
|
||||
|
||||
以 `use*` 开头的方法表示它是一个 [Vue 3 组合式 API](https://cn.vuejs.org/guide/introduction.html#composition-api) 函数,只能在 `setup()` 内部使用或者使用 `<script setup>`。
|
||||
|
||||
## `useData`
|
||||
|
||||
返回页面的属性数据,返回的对象具有以下类型:
|
||||
|
||||
```ts
|
||||
interface VitePressData<T = any> {
|
||||
site: Ref<SiteData<T>>
|
||||
page: Ref<PageData>
|
||||
theme: Ref<T> // themeConfig from .vitepress/config.js
|
||||
frontmatter: Ref<PageData['frontmatter']>
|
||||
title: Ref<string>
|
||||
description: Ref<string>
|
||||
lang: Ref<string>
|
||||
isDark: Ref<boolean>
|
||||
dir: Ref<string>
|
||||
localeIndex: Ref<string>
|
||||
}
|
||||
```
|
||||
|
||||
**例子:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
|
||||
const { theme } = useData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ theme.footer.copyright }}</h1>
|
||||
</template>
|
||||
```
|
||||
|
||||
## `useRoute`
|
||||
|
||||
返回具有以下类型的当前路由对象:
|
||||
|
||||
```ts
|
||||
interface Route {
|
||||
path: string
|
||||
data: PageData
|
||||
component: Component | null
|
||||
}
|
||||
```
|
||||
|
||||
## `useRouter`
|
||||
|
||||
返回 VitePress 路由实例,用来以编程方式导航到另一个页面。
|
||||
|
||||
```ts
|
||||
interface Router {
|
||||
route: Route
|
||||
go: (href?: string) => Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
## `withBase`
|
||||
|
||||
- **Type**: `(path: string) => string`
|
||||
|
||||
将配置的 [`base`](/config/app-config#base) 添加到给定的 URL 路径。另请参阅 [Base URL](/guide/asset-handling#base-url)。
|
||||
|
||||
## `<Content />`
|
||||
|
||||
`<Content />` 组件显示渲染的 markdown 内容。这在[创建你自己的主题时](/guide/customization-intro)很有用。
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
<Content />
|
||||
</template>
|
||||
```
|
||||
|
||||
## `<ClientOnly />`
|
||||
|
||||
`<ClientOnly />` 组件只在客户端渲染它的插槽。
|
||||
|
||||
由于 VitePress 应用在生成静态文件之后会在 Node.js 中进行服务端渲染,因此任何 Vue 的使用都必须符合通用代码的要求。简而言之,确保只在 beforeMount 或 mounted 钩子中访问浏览器以及 DOM API。
|
||||
|
||||
如果你正在使用不支持 SSR 的组件 (例如,包含自定义指令),你可以将它们包装在 `ClientOnly` 组件中。
|
||||
|
||||
```vue-html
|
||||
<ClientOnly>
|
||||
<NonSSRFriendlyComponent />
|
||||
</ClientOnly>
|
||||
```
|
||||
@ -1,192 +0,0 @@
|
||||
# Frontmatter 配置 {#frontmatter-config}
|
||||
|
||||
Frontmatter 支持基于页面的配置。在每个标签上,你可以自由地添加任何设置来覆盖任何全局应用或主题配置。此外,还有一些配置,你只能在 Frontmatter 中定义。
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: Docs with VitePress
|
||||
editLink: true
|
||||
---
|
||||
```
|
||||
|
||||
你可以通过 `$frontmatter` 在任何 markdown 文件中访问 frontmatter。
|
||||
|
||||
```md
|
||||
{{ $frontmatter.title }}
|
||||
```
|
||||
|
||||
## title
|
||||
|
||||
- Type: `string`
|
||||
|
||||
页面的标题。它与 [config.title](../config/app-config#title) 相同,并覆盖了应用全局配置。
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: VitePress
|
||||
---
|
||||
```
|
||||
|
||||
## titleTemplate
|
||||
|
||||
- Type: `string | boolean`
|
||||
|
||||
标题的后缀。它与 [config.titleTemplate](../config/app-config#titletemplate) 相同,并覆盖了应用全局配置。
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: VitePress
|
||||
titleTemplate: Vite & Vue powered static site generator
|
||||
---
|
||||
```
|
||||
|
||||
## description
|
||||
|
||||
- Type: `string`
|
||||
|
||||
页面的描述。它与 [config.description](../config/app-config#description) 相同,并覆盖了应用全局配置。
|
||||
|
||||
```yaml
|
||||
---
|
||||
description: VitePress
|
||||
---
|
||||
```
|
||||
|
||||
## head
|
||||
|
||||
- Type: `HeadConfig[]`
|
||||
|
||||
指定要注入的额外 head 标签。
|
||||
|
||||
```yaml
|
||||
---
|
||||
head:
|
||||
- - meta
|
||||
- name: description
|
||||
content: hello
|
||||
- - meta
|
||||
- name: keywords
|
||||
content: super duper SEO
|
||||
---
|
||||
```
|
||||
|
||||
```ts
|
||||
type HeadConfig =
|
||||
| [string, Record<string, string>]
|
||||
| [string, Record<string, string>, string]
|
||||
```
|
||||
|
||||
## lastUpdated
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
|
||||
在当前页面是否显示[最后更新](../guide/theme-last-updated)文本。
|
||||
|
||||
```yaml
|
||||
---
|
||||
lastUpdated: false
|
||||
---
|
||||
```
|
||||
|
||||
## layout
|
||||
|
||||
- Type: `doc | home | page`
|
||||
- Default: `doc`
|
||||
|
||||
决定页面的布局。
|
||||
|
||||
- `doc` - It applies default documentation styles to the markdown content.
|
||||
- `home` - Special layout for "Home Page". You may add extra options such as `hero` and `features` to rapidly create beautiful landing page.
|
||||
- `page` - Behave similar to `doc` but it applies no styles to the content. Useful when you want to create a fully custom page.
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: doc
|
||||
---
|
||||
```
|
||||
|
||||
## hero
|
||||
|
||||
- Type: `Hero`
|
||||
|
||||
This option only takes effect when `layout` is set to `home`.
|
||||
|
||||
It defines contents of home hero section.
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: VitePress
|
||||
text: Vite & Vue powered static site generator.
|
||||
tagline: Lorem ipsum...
|
||||
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 {
|
||||
// The string shown top of `text`. Comes with brand color
|
||||
// and expected to be short, such as product name.
|
||||
name?: string
|
||||
|
||||
// The main text for the hero section. This will be defined
|
||||
// as `h1` tag.
|
||||
text: string
|
||||
|
||||
// Tagline displayed below `text`.
|
||||
tagline?: string
|
||||
|
||||
// Action buttons to display in home hero section.
|
||||
actions?: HeroAction[]
|
||||
}
|
||||
|
||||
interface HeroAction {
|
||||
// Color theme of the button. Defaults to `brand`.
|
||||
theme?: 'brand' | 'alt'
|
||||
|
||||
// Label of the button.
|
||||
text: string
|
||||
|
||||
// Destination link of the button.
|
||||
link: string
|
||||
}
|
||||
```
|
||||
|
||||
## features
|
||||
|
||||
- Type: `Feature[]`
|
||||
|
||||
This option only takes effect when `layout` is set to `home`.
|
||||
|
||||
It defines items to display in features section.
|
||||
|
||||
You may learn more about it in [Theme: Home Page](../guide/theme-home-page).
|
||||
|
||||
## aside
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
|
||||
If you want the right aside component in `doc` layout not to be shown, set this option to `false`.
|
||||
|
||||
```yaml
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
```
|
||||
|
||||
## outline
|
||||
|
||||
- Type: `number | [number, number] | 'deep' | false`
|
||||
- Default: `2`
|
||||
|
||||
The levels of header in the outline to display for the page. It's same as [config.themeConfig.outline](../config/theme-config#outline), and it overrides the theme config.
|
||||
@ -1,76 +0,0 @@
|
||||
# 简介 {#introduction}
|
||||
|
||||
将配置文件放在 `.vitepress/config.js` 中。 这是放置所有 VitePress 特定文件的地方。
|
||||
|
||||
```
|
||||
.
|
||||
├─ docs
|
||||
│ ├─ .vitepress
|
||||
│ │ └─ config.js
|
||||
│ └─ index.md
|
||||
└─ package.json
|
||||
```
|
||||
|
||||
::: tip 提示
|
||||
你也可以使用任意的 `.ts`、`.cjs`、`.mjs`、`.cts` 和 `.mts` 作为配置文件的扩展名。
|
||||
:::
|
||||
|
||||
VitePress 带有 2 种类型的配置。一种是[应用全局配置](./app-config),它配置站点的基本功能,例如设置站点的标题,或自定义 Markdown 解析器的工作方式。其次是[主题配置](./theme-config),用于配置站点的主题,例如添加侧边栏,或者添加“在 GitHub 上编辑此页面”链接等功能。
|
||||
|
||||
你还可以在 [Frontmatter](./frontmatter-config) 中进行另一种配置。Frontmatter 配置可以覆盖在该特定页面的应用全局配置或主题配置上定义的全局配置。但是,有几个选项也仅在 frontmatter 中可用。
|
||||
|
||||
请参阅相应的配置页面以了解更多信息。
|
||||
|
||||
## 配置智能提示 {#config-intellisense}
|
||||
|
||||
由于 VitePress 附带 TypeScript 类型,你可以利用 IDE 的智能提示和 jsdoc 类型提示:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @type {import('vitepress').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
// ...
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
或者,你可以使用 `defineConfig` 辅助函数,它会提供智能提示,而无需 jsdoc 注释:
|
||||
|
||||
```js
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
VitePress 也直接支持 TS 配置文件。 你也可以将 `.vitepress/config.ts` 与 `defineConfig` 辅助函数一起使用。
|
||||
|
||||
## 主题配置类型 {#typed-theme-config}
|
||||
|
||||
默认情况下,`defineConfig` 辅助函数使用默认主题的主题配置类型:
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
themeConfig: {
|
||||
// Type is `DefaultTheme.Config`
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
如果你使用自定义主题并希望对主题配置进行类型检查,则需要使用 `defineConfigWithTheme`,并通过通用参数传递自定义主题的配置类型:
|
||||
|
||||
```ts
|
||||
import { defineConfigWithTheme } from 'vitepress'
|
||||
import { ThemeConfig } from 'your-theme'
|
||||
|
||||
export default defineConfigWithTheme<ThemeConfig>({
|
||||
themeConfig: {
|
||||
// Type is `ThemeConfig`
|
||||
}
|
||||
})
|
||||
```
|
||||
@ -0,0 +1,56 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Connecting to a CMS
|
||||
|
||||
## General Workflow
|
||||
|
||||
Connecting VitePress to a CMS will largely revolve around [Dynamic Routes](/guide/routing#dynamic-routes). Make sure to understand how it works before proceeding.
|
||||
|
||||
Since each CMS will work differently, here we can only provide a generic workflow that you will need to adapt to your specific scenario.
|
||||
|
||||
1. If your CMS requires authentication, create an `.env` file to store your API tokens and load it so:
|
||||
|
||||
```js
|
||||
// posts/[id].paths.js
|
||||
import { loadEnv } from 'vitepress'
|
||||
|
||||
const env = loadEnv('', process.cwd())
|
||||
```
|
||||
|
||||
2. Fetch the necessary data from the CMS and format it into proper paths data:
|
||||
|
||||
```js
|
||||
export default {
|
||||
async paths() {
|
||||
// use respective CMS client library if needed
|
||||
const data = await (await fetch('https://my-cms-api', {
|
||||
headers: {
|
||||
// token if necessary
|
||||
}
|
||||
})).json()
|
||||
|
||||
return data.map(entry => {
|
||||
return {
|
||||
params: { id: entry.id, /* title, authors, date etc. */ },
|
||||
content: entry.content
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Render the content in the page:
|
||||
|
||||
```md
|
||||
# {{ $params.title }}
|
||||
|
||||
- by {{ $params.author }} on {{ $params.date }}
|
||||
|
||||
<!-- @content -->
|
||||
```
|
||||
|
||||
## Integration Guides
|
||||
|
||||
If you have written a guide on integrating VitePress with a specific CMS, please use the "Edit this page" link below to submit it here!
|
||||
@ -1,27 +0,0 @@
|
||||
# 配置 {#configuration}
|
||||
|
||||
当没有任何配置的时候,页面将非常轻量,但用户也无法通过导航去访问站点。要自定义站点,首先在 docs 目录里创建一个 `.vitepress` 目录。 这是放置所有 VitePress 特定文件的地方。 这时候你的项目结构大概是这样的:
|
||||
|
||||
```
|
||||
.
|
||||
├─ docs
|
||||
│ ├─ .vitepress
|
||||
│ │ └─ config.js
|
||||
│ └─ index.md
|
||||
└─ package.json
|
||||
```
|
||||
|
||||
配置 VitePress 站点的基本文件是 `.vitepress/config.js`,它应该导出一个 JavaScript 对象:
|
||||
|
||||
```js
|
||||
export default {
|
||||
title: 'VitePress',
|
||||
description: 'Just playing around.'
|
||||
}
|
||||
```
|
||||
|
||||
在上面的示例中,该站点使用 `VitePress` 作为标题,`Just play around.` 作为站点的描述。
|
||||
|
||||
在[主题:介绍](./customization-intro)里了解有关 VitePress 功能特性,以了解如何在此配置文件中配置特定功能。
|
||||
|
||||
你还可以在[配置](../config/introduction)中找到所有配置项。
|
||||
@ -0,0 +1,222 @@
|
||||
# Using a Custom Theme
|
||||
|
||||
## Theme Resolving
|
||||
|
||||
You can enable a custom theme by creating a `.vitepress/theme/index.js` or `.vitepress/theme/index.ts` file (the "theme entry file"):
|
||||
|
||||
```
|
||||
.
|
||||
├─ docs # project root
|
||||
│ ├─ .vitepress
|
||||
│ │ ├─ theme
|
||||
│ │ │ └─ index.js # theme entry
|
||||
│ │ └─ config.js # config file
|
||||
│ └─ index.md
|
||||
└─ package.json
|
||||
```
|
||||
|
||||
VitePress will always use the custom theme instead of the default theme when it detects presence of a theme entry file. You can, however, [extend the default theme](./extending-default-theme) to perform advanced customizations on top of it.
|
||||
|
||||
## Theme Interface
|
||||
|
||||
A VitePress custom theme is defined as an object with the following interface:
|
||||
|
||||
```ts
|
||||
interface Theme {
|
||||
/**
|
||||
* Root layout component for every page
|
||||
* @required
|
||||
*/
|
||||
Layout: Component
|
||||
/**
|
||||
* Enhance Vue app instance
|
||||
* @optional
|
||||
*/
|
||||
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
|
||||
/**
|
||||
* Extend another theme, calling its `enhanceApp` before ours
|
||||
* @optional
|
||||
*/
|
||||
extends?: Theme
|
||||
}
|
||||
|
||||
interface EnhanceAppContext {
|
||||
app: App // Vue app instance
|
||||
router: Router // VitePress router instance
|
||||
siteData: Ref<SiteData> // Site-level metadata
|
||||
}
|
||||
```
|
||||
|
||||
The theme entry file should export the theme as its default export:
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
|
||||
// You can directly import Vue files in the theme entry
|
||||
// VitePress is pre-configured with @vitejs/plugin-vue.
|
||||
import Layout from './Layout.vue'
|
||||
|
||||
export default {
|
||||
Layout,
|
||||
enhanceApp({ app, router, siteData }) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The default export is the only contract for a custom theme, and only the `Layout` property is required. So technically, a VitePress theme can be as simple as a single Vue component.
|
||||
|
||||
Inside your layout component, it works just like a normal Vite + Vue 3 application. Do note the theme also needs to be [SSR-compatible](./using-vue#browser-api-access-restrictions).
|
||||
|
||||
## Building a Layout
|
||||
|
||||
The most basic layout component needs to contain a [`<Content />`](/reference/runtime-api#content) component:
|
||||
|
||||
```vue
|
||||
<!-- .vitepress/theme/Layout.vue -->
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
|
||||
<!-- this is where markdown content will be rendered -->
|
||||
<Content />
|
||||
</template>
|
||||
```
|
||||
|
||||
The above layout simply renders every page's markdown as HTML. The first improvement we can add is to handle 404 errors:
|
||||
|
||||
```vue{1-4,9-12}
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
const { page } = useData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
|
||||
<div v-if="page.isNotFound">
|
||||
Custom 404 page!
|
||||
</div>
|
||||
<Content v-else />
|
||||
</template>
|
||||
```
|
||||
|
||||
The [`useData()`](/reference/runtime-api#usedata) helper provides us with all the runtime data we need to conditionally render different layouts. One of the other data we can access is the current page's frontmatter. We can leverage this to allow the end user to control the layout in each page. For example, the user can indicate the page should use a special home page layout with:
|
||||
|
||||
```md
|
||||
---
|
||||
layout: home
|
||||
---
|
||||
```
|
||||
|
||||
And we can adjust our theme to handle this:
|
||||
|
||||
```vue{3,12-14}
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
const { page, frontmatter } = useData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
|
||||
<div v-if="page.isNotFound">
|
||||
Custom 404 page!
|
||||
</div>
|
||||
<div v-if="frontmatter.layout === 'home'">
|
||||
Custom home page!
|
||||
</div>
|
||||
<Content v-else />
|
||||
</template>
|
||||
```
|
||||
|
||||
You can, of course, split the layout into more components:
|
||||
|
||||
```vue{3-5,12-15}
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
import NotFound from './NotFound.vue'
|
||||
import Home from './Home.vue'
|
||||
import Page from './Page.vue'
|
||||
|
||||
const { page, frontmatter } = useData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
|
||||
<NotFound v-if="page.isNotFound" />
|
||||
<Home v-if="frontmatter.layout === 'home'" />
|
||||
<Page v-else /> <!-- <Page /> renders <Content /> -->
|
||||
</template>
|
||||
```
|
||||
|
||||
Consult the [Runtime API Reference](/reference/runtime-api) for everything available in theme components. In addition, you can leverage [Build-Time Data Loading](./data-loading) to generate data-driven layout - for example, a page that lists all blog posts in the current project.
|
||||
|
||||
## Distributing a Custom Theme
|
||||
|
||||
The easiest way to distribute a custom theme is by providing it as a [template repository on GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository).
|
||||
|
||||
If you wish to distribute the theme as an npm package, follow these steps:
|
||||
|
||||
1. Export the theme object as the default export in your package entry.
|
||||
|
||||
2. If applicable, export your theme config type definition as `ThemeConfig`.
|
||||
|
||||
3. If your theme requires adjusting the VitePress config, export that config under a package sub-path (e.g. `my-theme/config`) so the user can extend it.
|
||||
|
||||
4. Document the theme config options (both via config file and frontmatter).
|
||||
|
||||
5. Provide clear instructions on how to consume your theme (see below).
|
||||
|
||||
## Consuming a Custom Theme
|
||||
|
||||
To consume an external theme, import and re-export it from the custom theme entry:
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import Theme from 'awesome-vitepress-theme'
|
||||
|
||||
export default Theme
|
||||
```
|
||||
|
||||
If the theme needs to be extended:
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import Theme from 'awesome-vitepress-theme'
|
||||
|
||||
export default {
|
||||
extends: Theme,
|
||||
enhanceApp(ctx) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the theme requires special VitePress config, you will need to also extend it in your own config:
|
||||
|
||||
```ts
|
||||
// .vitepress/theme/config.ts
|
||||
import baseConfig from 'awesome-vitepress-theme/config'
|
||||
|
||||
export default {
|
||||
// extend theme base config (if needed)
|
||||
extends: baseConfig
|
||||
}
|
||||
```
|
||||
|
||||
Finally, if the theme provides types for its theme config:
|
||||
|
||||
```ts
|
||||
// .vitepress/theme/config.ts
|
||||
import baseConfig from 'awesome-vitepress-theme/config'
|
||||
import { defineConfigWithTheme } from 'vitepress'
|
||||
import type { ThemeConfig } from 'awesome-vitepress-theme'
|
||||
|
||||
export default defineConfigWithTheme<ThemeConfig>({
|
||||
extends: baseConfig,
|
||||
themeConfig: {
|
||||
// Type is `ThemeConfig`
|
||||
}
|
||||
})
|
||||
```
|
||||
@ -0,0 +1,230 @@
|
||||
# Deploy Your VitePress Site
|
||||
|
||||
The following guides are based on some shared assumptions:
|
||||
|
||||
- You are placing your docs inside the `docs` directory of your project.
|
||||
- You are using the default build output location (`.vitepress/dist`).
|
||||
- VitePress is installed as a local dependency in your project, and you have set up the following scripts in your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
If your site is to be served at a subdirectory (`https://example.com/subdir/`), then you have to set `'/subdir/'` as the [`base`](/reference/site-config#base) in your `docs/.vitepress/config.js`.
|
||||
|
||||
**Example:** If you're using Github (or GitLab) Pages and deploying to `user.github.io/repo/`, then set your `base` to `/repo/`.
|
||||
|
||||
:::
|
||||
|
||||
## Build and Test Locally
|
||||
|
||||
- You may run this command to build the docs:
|
||||
|
||||
```sh
|
||||
$ npm run docs:build
|
||||
```
|
||||
|
||||
- Once you've built the docs, you can test them locally by running:
|
||||
|
||||
```sh
|
||||
$ npm run docs:preview
|
||||
```
|
||||
|
||||
The `preview` command will boot up a local static web server that will serve the files from `.vitepress/dist` at `http://localhost:4173`. It's an easy way to check if the production build looks fine in your local environment.
|
||||
|
||||
- You can configure the port of the server by passing `--port` as an argument.
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"docs:preview": "vitepress preview docs --port 8080"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now the `docs:preview` method will launch the server at `http://localhost:8080`.
|
||||
|
||||
## Netlify, Vercel, AWS Amplify, Cloudflare Pages, Render
|
||||
|
||||
Set up a new project and change these settings using your dashboard:
|
||||
|
||||
- **Build Command:** `npm run docs:build`
|
||||
- **Output Directory:** `docs/.vitepress/dist`
|
||||
- **Node Version:** `14` (or above, by default it usually will be 14 or 16, but on Cloudflare Pages the default is still 12, so you may need to [change that](https://developers.cloudflare.com/pages/platform/build-configuration/))
|
||||
|
||||
::: warning
|
||||
Don't enable options like _Auto Minify_ for HTML code. It will remove comments from output which have meaning to Vue. You may see hydration mismatch errors if they get removed.
|
||||
:::
|
||||
|
||||
## GitHub Pages
|
||||
|
||||
### Using GitHub Actions
|
||||
|
||||
1. In your theme config file, `docs/.vitepress/config.js`, set the `base` property to the name of your GitHub repository. If you plan to deploy your site to `https://foo.github.io/bar/`, then you should set base to `'/bar/'`. It should always start and end with a slash.
|
||||
|
||||
2. Create a file named `deploy.yml` inside `.github/workflows` directory of your project with the following content:
|
||||
|
||||
```yaml
|
||||
name: Deploy
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: npm
|
||||
- run: npm install --frozen-lockfile
|
||||
- name: Build
|
||||
run: npm run docs:build
|
||||
- uses: actions/configure-pages@v2
|
||||
- uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: docs/.vitepress/dist
|
||||
- name: Deploy
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
```
|
||||
|
||||
::: tip
|
||||
Please replace the corresponding branch name. For example, if the branch you want to build is `master`, then you should replace `main` with `master` in the above file.
|
||||
:::
|
||||
|
||||
3. In your repository's Settings under Pages menu item, select `GitHub Actions` in Build and deployment's Source.
|
||||
|
||||
4. Now commit your code and push it to the `main` branch.
|
||||
|
||||
5. Wait for actions to complete.
|
||||
|
||||
6. In your repository's Settings under Pages menu item, click `Visit site`, then you can see your site. Your docs will automatically deploy each time you push.
|
||||
|
||||
## GitLab Pages
|
||||
|
||||
### Using GitLab CI
|
||||
|
||||
1. Set `outDir` in `docs/.vitepress/config.js` to `../public`.
|
||||
|
||||
2. Still in your config file, `docs/.vitepress/config.js`, set the `base` property to the name of your GitLab repository. If you plan to deploy your site to `https://foo.gitlab.io/bar/`, then you should set base to `'/bar/'`. It should always start and end with a slash.
|
||||
|
||||
3. Create a file called `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content:
|
||||
|
||||
```yaml
|
||||
image: node:16
|
||||
pages:
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
- npm install
|
||||
- npm run docs:build
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main
|
||||
```
|
||||
|
||||
4. Alternatively, if you want to use an _alpine_ version of node, you have to install `git` manually. In that case, the code above modifies to this:
|
||||
```yaml
|
||||
image: node:16-alpine
|
||||
pages:
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
before_script:
|
||||
- apk add git
|
||||
script:
|
||||
- npm install
|
||||
- npm run docs:build
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main
|
||||
```
|
||||
|
||||
## Azure Static Web Apps
|
||||
|
||||
1. Follow the [official documentation](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration).
|
||||
|
||||
2. Set these values in your configuration file (and remove the ones you don't require, like `api_location`):
|
||||
|
||||
- **`app_location`**: `/`
|
||||
- **`output_location`**: `docs/.vitepress/dist`
|
||||
- **`app_build_command`**: `npm run docs:build`
|
||||
|
||||
## Firebase
|
||||
|
||||
1. Create `firebase.json` and `.firebaserc` at the root of your project:
|
||||
|
||||
`firebase.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hosting": {
|
||||
"public": "docs/.vitepress/dist",
|
||||
"ignore": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`.firebaserc`:
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": {
|
||||
"default": "<YOUR_FIREBASE_ID>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. After running `npm run docs:build`, run this command to deploy:
|
||||
|
||||
```sh
|
||||
firebase deploy
|
||||
```
|
||||
|
||||
## Surge
|
||||
|
||||
1. After running `npm run docs:build`, run this command to deploy:
|
||||
|
||||
```sh
|
||||
npx surge docs/.vitepress/dist
|
||||
```
|
||||
|
||||
## Heroku
|
||||
|
||||
1. Follow documentation and guide given in [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static).
|
||||
|
||||
2. Create a file called `static.json` in the root of your project with the below content:
|
||||
|
||||
```json
|
||||
{
|
||||
"root": "docs/.vitepress/dist"
|
||||
}
|
||||
```
|
||||
|
||||
## Edgio
|
||||
|
||||
Refer [Creating and Deploying a VitePress App To Edgio](https://docs.edg.io/guides/vitepress).
|
||||
@ -0,0 +1,138 @@
|
||||
# Extending the Default Theme
|
||||
|
||||
VitePress' default theme is optimized for documentation, and can be customized. Consult the [Default Theme Config Overview](/reference/default-theme-config) for a comprehensive list of options.
|
||||
|
||||
However, there are a number of cases where configuration alone won't be enough. For example:
|
||||
|
||||
1. You need to tweak the CSS styling;
|
||||
2. You need to modify the Vue app instance, for example to register global components;
|
||||
3. You need to inject custom content into the theme via layout slots.
|
||||
|
||||
These advanced customizations will require using a custom theme that "extends" the default theme.
|
||||
|
||||
:::tip
|
||||
Before proceeding, make sure to first read [Using a Custom Theme](./custom-theme) to understand how custom themes work.
|
||||
:::
|
||||
|
||||
## Customizing CSS
|
||||
|
||||
The default theme CSS is customizable by overriding root level CSS variables:
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import './custom.css'
|
||||
|
||||
export default DefaultTheme
|
||||
```
|
||||
|
||||
```css
|
||||
/* .vitepress/theme/custom.css */
|
||||
:root {
|
||||
--vp-c-brand: #646cff;
|
||||
--vp-c-brand-light: #747bff;
|
||||
}
|
||||
```
|
||||
|
||||
See [default theme CSS variables](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) that can be overridden.
|
||||
|
||||
## Registering Global Components
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
enhanceApp(ctx) {
|
||||
// register your custom global components
|
||||
ctx.app.component('MyGlobalComponent' /* ... */)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Since we are using Vite, you can also leverage Vite's [glob import feature](https://vitejs.dev/guide/features.html#glob-import) to auto register a directory of components.
|
||||
|
||||
## Layout Slots
|
||||
|
||||
The default theme's `<Layout/>` component has a few slots that can be used to inject content at certain locations of the page. Here's an example of injecting a component into the before outline:
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import MyLayout from './MyLayout.vue'
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
// override the Layout with a wrapper component that
|
||||
// injects the slots
|
||||
Layout: MyLayout
|
||||
}
|
||||
```
|
||||
|
||||
```vue
|
||||
<!--.vitepress/theme/MyLayout.vue-->
|
||||
<script setup>
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
|
||||
const { Layout } = DefaultTheme
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<template #aside-outline-before>
|
||||
My custom sidebar top content
|
||||
</template>
|
||||
</Layout>
|
||||
</template>
|
||||
```
|
||||
|
||||
Or you could use render function as well.
|
||||
|
||||
```js
|
||||
// .vitepress/theme/index.js
|
||||
import { h } from 'vue'
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import MyComponent from './MyComponent.vue'
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
Layout() {
|
||||
return h(DefaultTheme.Layout, null, {
|
||||
'aside-outline-before': () => h(MyComponent)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Full list of slots available in the default theme layout:
|
||||
|
||||
- When `layout: 'doc'` (default) is enabled via frontmatter:
|
||||
- `doc-footer-before`
|
||||
- `doc-before`
|
||||
- `doc-after`
|
||||
- `sidebar-nav-before`
|
||||
- `sidebar-nav-after`
|
||||
- `aside-top`
|
||||
- `aside-bottom`
|
||||
- `aside-outline-before`
|
||||
- `aside-outline-after`
|
||||
- `aside-ads-before`
|
||||
- `aside-ads-after`
|
||||
- When `layout: 'home'` is enabled via frontmatter:
|
||||
- `home-hero-before`
|
||||
- `home-hero-info`
|
||||
- `home-hero-image`
|
||||
- `home-hero-after`
|
||||
- `home-features-before`
|
||||
- `home-features-after`
|
||||
- Always:
|
||||
- `layout-top`
|
||||
- `layout-bottom`
|
||||
- `nav-bar-title-before`
|
||||
- `nav-bar-title-after`
|
||||
- `nav-bar-content-before`
|
||||
- `nav-bar-content-after`
|
||||
- `nav-screen-content-before`
|
||||
- `nav-screen-content-after`
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
# 从 VitePress 0.x 迁移 {#migration-from-vitepress-0-x}
|
||||
# Migration from VitePress 0.x
|
||||
|
||||
如果你来自 VitePress 0.x 版本,由于新功能和增强功能,会有一些重大更改。 请按照本指南了解如何将你的应用程序迁移到最新的 VitePress。
|
||||
If you're coming from VitePress 0.x version, there're several breaking changes due to new features and enhancement. Please follow this guide to see how to migrate your app over to the latest VitePress.
|
||||
|
||||
## 应用全局配置 {#app-config}
|
||||
## App Config
|
||||
|
||||
- 国际化功能尚未实现。
|
||||
- The internationalization feature is not yet implemented.
|
||||
|
||||
## 主题配置 {#theme-config}
|
||||
## Theme Config
|
||||
|
||||
- `sidebar` 选项改变了它的结构。
|
||||
- `children` key现在命名为 `items`。
|
||||
- 顶级项目目前可能不包含 `link`。我们打算把它转回来。
|
||||
- 删除了`repo`、`repoLabel`、`docsDir`、`docsBranch`、`editLinks`、`editLinkText`,以支持更灵活的 api。
|
||||
- 要将带有图标的 GitHub 链接添加到导航,请使用[社交链接](./theme-nav#navigation-links)功能。
|
||||
- 要添加“编辑此页面”功能,请使用[编辑链接](./theme-edit-link)功能。
|
||||
- `lastUpdated` 选项现在分为 `config.lastUpdated` 和 `themeConfig.lastUpdatedText`。
|
||||
- `carbonAds.carbon` 更改为 `carbonAds.code`。
|
||||
- `sidebar` option has changed its structure.
|
||||
- `children` key is now named `items`.
|
||||
- Top level item may not contain `link` at the moment. We're planning to bring it back.
|
||||
- `repo`, `repoLabel`, `docsDir`, `docsBranch`, `editLinks`, `editLinkText` are removed in favor of more flexible api.
|
||||
- For adding GitHub link with icon to the nav, use [Social Links](/reference/default-theme-nav#navigation-links) feature.
|
||||
- For adding "Edit this page" feature, use [Edit Link](/reference/default-theme-edit-link) feature.
|
||||
- `lastUpdated` option is now split into `config.lastUpdated` and `themeConfig.lastUpdatedText`.
|
||||
- `carbonAds.carbon` is changed to `carbonAds.code`.
|
||||
|
||||
## Frontmatter 配置 {#frontmatter-config}
|
||||
## Frontmatter Config
|
||||
|
||||
- `home: true` 选项已更改为 `layout: home`。此外,还修改了许多与主页相关的设置以提供附加功能。详情请参阅[主页指南](./theme-home-page)。
|
||||
- `footer` 选项移至 [`themeConfig.footer`](../config/theme-config#footer)。
|
||||
- `home: true` option has changed to `layout: home`. Also, many Homepage related settings have been modified to provide additional features. See [Home Page guide](/reference/default-theme-home-page) for details.
|
||||
- `footer` option is moved to [`themeConfig.footer`](/reference/default-theme-config#footer).
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
# MPA Mode <Badge type="warning" text="experimental" />
|
||||
|
||||
MPA (Multi-Page Application) mode can be enabled via the command line via `vitepress build --mpa`, or via config through the `mpa: true` option.
|
||||
|
||||
In MPA mode, all pages are rendered without any JavaScript included by default. As a result, the production site will likely have a better initial visit performance score from audit tools.
|
||||
|
||||
However, due to the absence of SPA navigation, cross-page links will lead to full page reloads. Post-load navigations in MPA mode will not feel as instant as in SPA mode.
|
||||
|
||||
Also note that no-JS-by-default also means you are essentially using Vue purely as a server-side templating language - no event handlers will be attached in the browser, so there will be no interactivity. To load client-side JavaScript, you can do so by using the special `<script client>` tag (works in both `.md` and `.vue` files, but only in MPA mode):
|
||||
|
||||
```html
|
||||
<script client>
|
||||
document.querySelector('h1').addEventListener('click', () => {
|
||||
console.log('client side JavaScript!')
|
||||
})
|
||||
</script>
|
||||
|
||||
# Hello
|
||||
```
|
||||
|
||||
Client scripts in all theme components will be bundled together, while client script for a specific page will be split for that page only.
|
||||
|
||||
Notice that `<script client>` is **not evaluated as Vue component code**: it's processed as a plain JavaScript module. For this reason, MPA mode should only be used if your site requires absolutely minimal client-side interactivity.
|
||||
@ -1,28 +0,0 @@
|
||||
# 编辑链接 {#edit-link}
|
||||
|
||||
编辑链接可以显示链接以编辑 Git 管理服务 (例如 GitHub 或 GitLab) 上的页面。 可以通过 `themeConfig.editLink` 选项配置来启用。
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`pattern` 选项定义了链接的 URL 结构,`:path` 将被页面路径替换。
|
||||
|
||||
默认情况下,这将在文档页面底部添加链接文本“编辑此页面”。你可以通过定义 `text` 选项来自定义此文本。
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
|
||||
text: 'Edit this page on GitHub'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -1,26 +0,0 @@
|
||||
# 页脚 {#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 {
|
||||
// The message shown rigth before copyright.
|
||||
message?: string
|
||||
|
||||
// The actual copyright text.
|
||||
copyright?: string
|
||||
}
|
||||
```
|
||||
|
||||
注意,当[侧边栏](./theme-sidebar)可见时,不会显示页脚。
|
||||
@ -1,20 +0,0 @@
|
||||
# 最后更新 {#last-updated}
|
||||
|
||||
最后内容的更新时间将显示在页面的右下角。要启用它,请在你的配置中添加 `lastUpdated` 选项。
|
||||
## 页面配置 {#page-configuration}
|
||||
|
||||
添加 `lastUpdated` 选项到配置中去。
|
||||
```js
|
||||
export default {
|
||||
lastUpdated: true
|
||||
}
|
||||
```
|
||||
|
||||
## Frontmatter 配置 {#frontmatter-configuration}
|
||||
如果你想隐藏最后更新的文本,请对 `lastUpdated` 选项设置为 false。
|
||||
|
||||
```yaml
|
||||
---
|
||||
lastUpdated: false
|
||||
---
|
||||
```
|
||||
@ -1,161 +0,0 @@
|
||||
# 侧边栏 {#sidebar}
|
||||
|
||||
侧边栏是文档的主要导航块。可以在 `themeConfig.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: [
|
||||
// This shows `/guide/index.md` page.
|
||||
{ text: 'Introduction', link: '/guide/' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 多个侧边栏 {#multiple-sidebars}
|
||||
|
||||
你可能会根据页面路径显示不同的侧边栏。例如,如本站点所示,你可能希望在文档中创建单独的内容部分,例如“指南”页面和“配置”页面。
|
||||
|
||||
为此,首先将你的页面放到所在的目录中:
|
||||
|
||||
```
|
||||
.
|
||||
├─ guide/
|
||||
│ ├─ index.md
|
||||
│ ├─ one.md
|
||||
│ └─ two.md
|
||||
└─ config/
|
||||
├─ index.md
|
||||
├─ three.md
|
||||
└─ four.md
|
||||
```
|
||||
|
||||
然后,更新配置以定义每个部分的侧边栏,不同的是,这次配置的是一个对象而不是数组。
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: {
|
||||
// 当用户在 `指南` 目录页面下将会展示这个侧边栏
|
||||
'/guide/': [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
// This shows `/guide/index.md` page.
|
||||
{ text: 'Index', link: '/guide/' }, // /guide/index.md
|
||||
{ text: 'One', link: '/guide/one' }, // /guide/one.md
|
||||
{ text: 'Two', link: '/guide/two' } // /guide/two.md
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
// 当用户在 `配置` 目录页面下将会展示这个侧边栏
|
||||
'/config/': [
|
||||
{
|
||||
text: 'Config',
|
||||
items: [
|
||||
// This shows `/config/index.md` page.
|
||||
{ text: 'Index', link: '/config/' }, // /config/index.md
|
||||
{ text: 'Three', link: '/config/three' }, // /config/three.md
|
||||
{ text: 'Four', link: '/config/four' } // /config/four.md
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 可折叠的侧边栏组 {#collapsible-sidebar-groups}
|
||||
|
||||
通过向侧边栏组添加 `collapsible` 选项,它会显示一个切换按钮来隐藏或显示子菜单。
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Section Title A',
|
||||
collapsible: true,
|
||||
items: [...]
|
||||
},
|
||||
{
|
||||
text: 'Section Title B',
|
||||
collapsible: true,
|
||||
items: [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
默认情况下,所有侧边栏都是展开的。如果你希望它们在初始页面加载时关闭,请将 `collapsed` 选项设置为 `true`。
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Section Title A',
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
items: [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,74 @@
|
||||
# Command Line Interface
|
||||
|
||||
## `vitepress dev`
|
||||
|
||||
Start VitePress dev server using designated directory as root. Defaults to current directory. The `dev` command can also be omitted when running in current directory.
|
||||
|
||||
### Usage
|
||||
|
||||
```sh
|
||||
# start in current directory, omitting `dev`
|
||||
vitepress
|
||||
|
||||
# start in sub directory
|
||||
vitepress dev [root]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
| - | - |
|
||||
| `--open [path]` | Open browser on startup (`boolean \| string`) |
|
||||
| `--port <port>` | Specify port (`number`) |
|
||||
| `--base <path>` | Public base path (default: `/`) (`string`) |
|
||||
| `--cors` | Enable CORS |
|
||||
| `--strictPort` | Exit if specified port is already in use (`boolean`) |
|
||||
| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) |
|
||||
|
||||
## `vitepress build`
|
||||
|
||||
Build the VitePress site for production.
|
||||
|
||||
### Usage
|
||||
|
||||
```sh
|
||||
vitepress build [root]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
| - | - |
|
||||
| `--mpa` (experimental) | Build in [MPA mode](/guide/mpa-mode) without client-side hydration (`boolean`) |
|
||||
| `--base <path>` | Public base path (default: `/`) (`string`) |
|
||||
| `--target <target>` | Transpile target (default: `"modules"`) (`string`) |
|
||||
| `--outDir <dir>` | Output directory (default: `.vitepress/dist`) (`string`) |
|
||||
| `--minify [minifier]` | Enable/disable minification, or specify minifier to use (default: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) |
|
||||
| `--assetsInlineLimit <number>` | Static asset base64 inline threshold in bytes (default: `4096`) (`number`) |
|
||||
|
||||
## `vitepress preview`
|
||||
|
||||
Locally preview the production build.
|
||||
|
||||
### Usage
|
||||
|
||||
```sh
|
||||
vitepress preview [root]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
| - | - |
|
||||
| `--base <path>` | Public base path (default: `/`) (`string`) |
|
||||
| `--port <port>` | Specify port (`number`) |
|
||||
|
||||
## `vitepress init`
|
||||
|
||||
Start the [Setup Wizard](/guide/getting-started#setup-wizard) in current directory.
|
||||
|
||||
### Usage
|
||||
|
||||
```sh
|
||||
vitepress init
|
||||
```
|
||||
@ -0,0 +1,22 @@
|
||||
# Carbon Ads
|
||||
|
||||
VitePress has built in native support for [Carbon Ads](https://www.carbonads.net/). By defining the Carbon Ads credentials in config, VitePress will display ads on the page.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
carbonAds: {
|
||||
code: 'your-carbon-code',
|
||||
placement: 'your-carbon-placement'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These values are used to call carbon CDN script as shown below.
|
||||
|
||||
```js
|
||||
`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}`
|
||||
```
|
||||
|
||||
To learn more about Carbon Ads configuration, please visit [Carbon Ads website](https://www.carbonads.net/).
|
||||
@ -0,0 +1,28 @@
|
||||
# Edit Link
|
||||
|
||||
Edit Link lets you display a link to edit the page on Git management services such as GitHub, or GitLab. To enable it, add `themeConfig.editLink` options to your config.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `pattern` option defines the URL structure for the link, and `:path` is going to be replaced with the page path.
|
||||
|
||||
By default, this will add the link text "Edit this page" at the bottom of the doc page. You may customize this text by defining the `text` option.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
|
||||
text: 'Edit this page on GitHub'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -0,0 +1,39 @@
|
||||
# Footer
|
||||
|
||||
VitePress will display global footer at the bottom of the page when `themeConfig.footer` is present.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
themeConfig: {
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2019-present Evan You'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
export interface Footer {
|
||||
// The message shown right before copyright.
|
||||
message?: string
|
||||
|
||||
// The actual copyright text.
|
||||
copyright?: string
|
||||
}
|
||||
```
|
||||
|
||||
The above configuration also supports HTML strings. So, for example, if you want to configure footer text to have some links, you can adjust the configuration as follows:
|
||||
|
||||
```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>'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that footer will not be displayed when the [SideBar](/reference/default-theme-sidebar) is visible.
|
||||
@ -0,0 +1,154 @@
|
||||
# Home Page
|
||||
|
||||
VitePress default theme provides a homepage layout, which you can also see used on [the homepage of this site](../). You may use it on any of your pages by specifying `layout: home` in the [frontmatter](./frontmatter-config).
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: home
|
||||
---
|
||||
```
|
||||
|
||||
However, this option alone wouldn't do much. You can add several different pre templated "sections" to the homepage by setting additional other options such as `hero` and `features`.
|
||||
|
||||
## Hero Section
|
||||
|
||||
The Hero section comes at the top of the homepage. Here's how you can configure the Hero section.
|
||||
|
||||
```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 {
|
||||
// The string shown top of `text`. Comes with brand color
|
||||
// and expected to be short, such as product name.
|
||||
name?: string
|
||||
|
||||
// The main text for the hero section. This will be defined
|
||||
// as `h1` tag.
|
||||
text: string
|
||||
|
||||
// Tagline displayed below `text`.
|
||||
tagline?: string
|
||||
|
||||
// The image is displayed next to the text and tagline area.
|
||||
image?: ThemeableImage
|
||||
|
||||
// Action buttons to display in home hero section.
|
||||
actions?: HeroAction[]
|
||||
}
|
||||
|
||||
type ThemeableImage =
|
||||
| string
|
||||
| { src: string; alt?: string }
|
||||
| { light: string; dark: string; alt?: string }
|
||||
|
||||
interface HeroAction {
|
||||
// Color theme of the button. Defaults to `brand`.
|
||||
theme?: 'brand' | 'alt'
|
||||
|
||||
// Label of the button.
|
||||
text: string
|
||||
|
||||
// Destination link of the button.
|
||||
link: string
|
||||
}
|
||||
```
|
||||
|
||||
### Customizing the name color
|
||||
|
||||
VitePress uses the brand color (`--vp-c-brand`) for the `name`. However, you may customize this color by overriding `--vp-home-hero-name-color` variable.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--vp-home-hero-name-color: blue;
|
||||
}
|
||||
```
|
||||
|
||||
Also you may customize it further by combining `--vp-home-hero-name-background` to give the `name` gradient color.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
|
||||
}
|
||||
```
|
||||
|
||||
## Features Section
|
||||
|
||||
In Features section, you can list any number of features you would like to show right after the Hero section. To configure it, pass `features` option to the frontmatter.
|
||||
|
||||
You can provide an icon for each feature, which can be an emoji or any type of image. When the configured icon is an image (svg, png, jpeg...), you must provide the icon with the proper width and height; you can also provide the description, its intrinsic size as well as its variants for dark and light theme when required.
|
||||
|
||||
```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 {
|
||||
// Show icon on each feature box.
|
||||
icon?: FeatureIcon
|
||||
|
||||
// Title of the feature.
|
||||
title: string
|
||||
|
||||
// Details of the feature.
|
||||
details: string
|
||||
|
||||
// Link when clicked on feature component. The link can
|
||||
// be both internal or external.
|
||||
//
|
||||
// e.g. `guid/reference/default-theme-home-page` or `htttps://example.com`
|
||||
link?: string
|
||||
|
||||
// Link text to be shown inside feature component. Best
|
||||
// used with `link` option.
|
||||
//
|
||||
// e.g. `Learn more`, `Visit page`, etc.
|
||||
linkText?: string
|
||||
}
|
||||
|
||||
type FeatureIcon =
|
||||
| string
|
||||
| { src: string; alt?: string; width?: string; height: string }
|
||||
| {
|
||||
light: string
|
||||
dark: string
|
||||
alt?: string
|
||||
width?: string
|
||||
height: string
|
||||
}
|
||||
```
|
||||
@ -0,0 +1,25 @@
|
||||
# Last Updated
|
||||
|
||||
The update time of the last content will be displayed in the lower right corner of the page.
|
||||
To enable it, add `lastUpdated` options to your config.
|
||||
|
||||
## Page Configuration
|
||||
|
||||
Add `lastUpdated` options to your config.
|
||||
|
||||
```js
|
||||
export default {
|
||||
lastUpdated: true
|
||||
}
|
||||
```
|
||||
|
||||
## Frontmatter Configuration
|
||||
|
||||
If you would like to hide the last update text, set false to the `lastUpdated` option.
|
||||
|
||||
```yaml
|
||||
---
|
||||
lastUpdated: false
|
||||
---
|
||||
```
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
# Layout
|
||||
|
||||
You may choose the page layout by setting `layout` option to the page [frontmatter](./frontmatter-config). There are 3 layout options, `doc`, `page`, and `home`. If nothing is specified, then the page is treated as `doc` page.
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: doc
|
||||
---
|
||||
```
|
||||
|
||||
## Doc Layout
|
||||
|
||||
Option `doc` is the default layout and it styles the whole Markdown content into "documentation" look. It works by wrapping whole content within `vp-doc` css class, and applying styles to elements underneath it.
|
||||
|
||||
Almost all generic elements such as `p`, or `h2` get special styling. Therefore, keep in mind that if you add any custom HTML inside a Markdown content, those will get affected by those styles as well.
|
||||
|
||||
It also provides documentation specific features listed below. These features are only enabled in this layout.
|
||||
|
||||
- Edit Link
|
||||
- Prev Next Link
|
||||
- Outline
|
||||
- [Carbon Ads](./default-theme-carbon-ads)
|
||||
|
||||
## Page Layout
|
||||
|
||||
Option `page` is treated as "blank page". The Markdown will still be parsed, and all of the [Markdown Extensions](/guide/markdown) work as same as `doc` layout, but it wouldn't get any default stylings.
|
||||
|
||||
The page layout will let you style everything by you without VitePress theme affecting the markup. This is useful when you want to create your own custom page.
|
||||
|
||||
Note that even in this layout, sidebar will still show up if the page has a matching sidebar config.
|
||||
|
||||
## Home Layout
|
||||
|
||||
Option `home` will generate templated "Homepage". In this layout, you can set extra options such as `hero` and `features` to customize the content further. Please visit [Default Theme: Home Page](/reference/default-theme-home-page) for more details.
|
||||
|
||||
## No Layout
|
||||
|
||||
If you don't want any layout, you can pass `layout: false` through frontmatter. This option is helpful if you want a fully-customizable landing page (without any sidebar, navbar, or footer by default).
|
||||
@ -0,0 +1,182 @@
|
||||
# Sidebar
|
||||
|
||||
The sidebar is the main navigation block for your documentation. You can configure the sidebar menu in [`themeConfig.sidebar`](/reference/default-theme-config#sidebar).
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Introduction', link: '/introduction' },
|
||||
{ text: 'Getting Started', link: '/getting-started' },
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## The Basics
|
||||
|
||||
The simplest form of the sidebar menu is passing in a single array of links. The first level item defines the "section" for the sidebar. It should contain `text`, which is the title of the section, and `items` which are the actual navigation links.
|
||||
|
||||
```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' },
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each `link` should specify the path to the actual file starting with `/`. If you add trailing slash to the end of link, it will show `index.md` of the corresponding directory.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
// This shows `/guide/index.md` page.
|
||||
{ text: 'Introduction', link: '/guide/' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You may further nest the sidebar items up to 6 level deep counting up from the root level. Note that deeper than 6 level of nested items gets ignored and will not be displayed on the sidebar.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Level 1',
|
||||
items: [
|
||||
{
|
||||
text: 'Level 2',
|
||||
items: [
|
||||
{
|
||||
text: 'Level 3',
|
||||
items: [
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple Sidebars
|
||||
|
||||
You may show different sidebar depending on the page path. For example, as shown on this site, you might want to create a separate sections of content in your documentation like "Guide" page and "Config" page.
|
||||
|
||||
To do so, first organize your pages into directories for each desired section:
|
||||
|
||||
```
|
||||
.
|
||||
├─ guide/
|
||||
│ ├─ index.md
|
||||
│ ├─ one.md
|
||||
│ └─ two.md
|
||||
└─ config/
|
||||
├─ index.md
|
||||
├─ three.md
|
||||
└─ four.md
|
||||
```
|
||||
|
||||
Then, update your configuration to define your sidebar for each section. This time, you should pass an object instead of an array.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: {
|
||||
// This sidebar gets displayed when a user
|
||||
// is on `guide` directory.
|
||||
'/guide/': [
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Index', link: '/guide/' },
|
||||
{ text: 'One', link: '/guide/one' },
|
||||
{ text: 'Two', link: '/guide/two' }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
// This sidebar gets displayed when a user
|
||||
// is on `config` directory.
|
||||
'/config/': [
|
||||
{
|
||||
text: 'Config',
|
||||
items: [
|
||||
{ text: 'Index', link: '/config/' },
|
||||
{ text: 'Three', link: '/config/three' },
|
||||
{ text: 'Four', link: '/config/four' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Collapsible Sidebar Groups
|
||||
|
||||
By adding `collapsed` option to the sidebar group, it shows a toggle button to hide/show each section.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Section Title A',
|
||||
collapsed: false,
|
||||
items: [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All sections are "open" by default. If you would like them to be "closed" on initial page load, set `collapsed` option to `true`.
|
||||
|
||||
```js
|
||||
export default {
|
||||
themeConfig: {
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Section Title A',
|
||||
collapsed: true,
|
||||
items: [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -0,0 +1,145 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Frontmatter Config
|
||||
|
||||
Frontmatter enables page based configuration. In every markdown file, you can use frontmatter config to override site-level or theme-level config options. Also, there are config options which you can only define in frontmatter.
|
||||
|
||||
Example usage:
|
||||
|
||||
```md
|
||||
---
|
||||
title: Docs with VitePress
|
||||
editLink: true
|
||||
---
|
||||
```
|
||||
|
||||
You can access frontmatter data via the `$frontmatter` global in Vue expressions:
|
||||
|
||||
```md
|
||||
{{ $frontmatter.title }}
|
||||
```
|
||||
|
||||
## title
|
||||
|
||||
- Type: `string`
|
||||
|
||||
Title for the page. It's same as [config.title](/reference/site-config#title), and it overrides the site-level config.
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: VitePress
|
||||
---
|
||||
```
|
||||
|
||||
## titleTemplate
|
||||
|
||||
- Type: `string | boolean`
|
||||
|
||||
The suffix for the title. It's same as [config.titleTemplate](/reference/site-config#titletemplate), and it overrides the site-level config.
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: VitePress
|
||||
titleTemplate: Vite & Vue powered static site generator
|
||||
---
|
||||
```
|
||||
|
||||
## description
|
||||
|
||||
- Type: `string`
|
||||
|
||||
Description for the page. It's same as [config.description](/reference/site-config#description), and it overrides the site-level config.
|
||||
|
||||
```yaml
|
||||
---
|
||||
description: VitePress
|
||||
---
|
||||
```
|
||||
|
||||
## head
|
||||
|
||||
- Type: `HeadConfig[]`
|
||||
|
||||
Specify extra head tags to be injected for the current page. Will be appended after head tags injected by site-level config.
|
||||
|
||||
```yaml
|
||||
---
|
||||
head:
|
||||
- - meta
|
||||
- name: description
|
||||
content: hello
|
||||
- - meta
|
||||
- name: keywords
|
||||
content: super duper SEO
|
||||
---
|
||||
```
|
||||
|
||||
```ts
|
||||
type HeadConfig =
|
||||
| [string, Record<string, string>]
|
||||
| [string, Record<string, string>, string]
|
||||
```
|
||||
|
||||
## Default Theme Only
|
||||
|
||||
The following frontmatter options are only applicable when using the default theme.
|
||||
|
||||
### layout <Badge type="info" text="default theme only" />
|
||||
|
||||
- Type: `doc | home | page`
|
||||
- Default: `doc`
|
||||
|
||||
Determines the layout of the page.
|
||||
|
||||
- `doc` - It applies default documentation styles to the markdown content.
|
||||
- `home` - Special layout for "Home Page". You may add extra options such as `hero` and `features` to rapidly create beautiful landing page.
|
||||
- `page` - Behave similar to `doc` but it applies no styles to the content. Useful when you want to create a fully custom page.
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: doc
|
||||
---
|
||||
```
|
||||
|
||||
### hero <Badge type="info" text="default theme only" /> <Badge type="info" text="Home page only" />
|
||||
|
||||
Defines contents of home hero section when `layout` is set to `home`. More details in [Default Theme: Home Page](/reference/default-theme-home-page).
|
||||
|
||||
### features <Badge type="info" text="default theme only" /> <Badge type="info" text="Home page only" />
|
||||
|
||||
Defines items to display in features section when `layout` is set to `home`. More details in [Default Theme: Home Page](/reference/default-theme-home-page).
|
||||
|
||||
### aside <Badge type="info" text="default theme only" />
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
|
||||
If you want the right aside component in `doc` layout not to be shown, set this option to `false`.
|
||||
|
||||
```yaml
|
||||
---
|
||||
aside: false
|
||||
---
|
||||
```
|
||||
|
||||
### outline <Badge type="info" text="default theme only" />
|
||||
|
||||
- Type: `number | [number, number] | 'deep' | false`
|
||||
- Default: `2`
|
||||
|
||||
The levels of header in the outline to display for the page. It's same as [config.themeConfig.outline](/reference/default-theme-config#outline), and it overrides the theme config.
|
||||
|
||||
### lastUpdated <Badge type="info" text="default theme only" />
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
|
||||
Whether to display [Last Updated](/reference/default-theme-last-updated) text in the current page.
|
||||
|
||||
```yaml
|
||||
---
|
||||
lastUpdated: false
|
||||
---
|
||||
```
|
||||
@ -0,0 +1,143 @@
|
||||
# Runtime API
|
||||
|
||||
VitePress offers several built-in APIs to let you access app data. VitePress also comes with a few built-in components that can be used globally.
|
||||
|
||||
The helper methods are globally importable from `vitepress` and are typically used in custom theme Vue components. However, they are also usable inside `.md` pages because markdown files are compiled into Vue [Single-File Components](https://vuejs.org/guide/scaling-up/sfc.html).
|
||||
|
||||
Methods that start with `use*` indicates that it is a [Vue 3 Composition API](https://vuejs.org/guide/introduction.html#composition-api) function ("Composable") that can only be used inside `setup()` or `<script setup>`.
|
||||
|
||||
## `useData` <Badge type="info" text="composable" />
|
||||
|
||||
Returns page-specific data. The returned object has the following type:
|
||||
|
||||
```ts
|
||||
interface VitePressData<T = any> {
|
||||
/**
|
||||
* Site-level metadata
|
||||
*/
|
||||
site: Ref<SiteData<T>>
|
||||
/**
|
||||
* themeConfig from .vitepress/config.js
|
||||
*/
|
||||
theme: Ref<T>
|
||||
/**
|
||||
* Page-level metadata
|
||||
*/
|
||||
page: Ref<PageData>
|
||||
/**
|
||||
* Page frontmatter
|
||||
*/
|
||||
frontmatter: Ref<PageData['frontmatter']>
|
||||
/**
|
||||
* Dynamic route params
|
||||
*/
|
||||
params: Ref<PageData['params']>
|
||||
title: Ref<string>
|
||||
description: Ref<string>
|
||||
lang: Ref<string>
|
||||
isDark: Ref<boolean>
|
||||
dir: Ref<string>
|
||||
localeIndex: Ref<string>
|
||||
}
|
||||
|
||||
interface PageData {
|
||||
title: string
|
||||
titleTemplate?: string | boolean
|
||||
description: string
|
||||
relativePath: string
|
||||
headers: Header[]
|
||||
frontmatter: Record<string, any>
|
||||
params?: Record<string, any>
|
||||
isNotFound?: boolean
|
||||
lastUpdated?: number
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { useData } from 'vitepress'
|
||||
|
||||
const { theme } = useData()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>{{ theme.footer.copyright }}</h1>
|
||||
</template>
|
||||
```
|
||||
|
||||
## `useRoute` <Badge type="info" text="composable" />
|
||||
|
||||
Returns the current route object with the following type:
|
||||
|
||||
```ts
|
||||
interface Route {
|
||||
path: string
|
||||
data: PageData
|
||||
component: Component | null
|
||||
}
|
||||
```
|
||||
|
||||
## `useRouter` <Badge type="info" text="composable" />
|
||||
|
||||
Returns the VitePress router instance so you can programmatically navigate to another page.
|
||||
|
||||
```ts
|
||||
interface Router {
|
||||
route: Route
|
||||
go: (href?: string) => Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
## `withBase` <Badge type="info" text="helper" />
|
||||
|
||||
- **Type**: `(path: string) => string`
|
||||
|
||||
Appends the configured [`base`](/reference/site-config#base) to a given URL path. Also see [Base URL](/guide/asset-handling#base-url).
|
||||
|
||||
## `<Content />` <Badge type="info" text="component" />
|
||||
|
||||
The `<Content />` component displays the rendered markdown contents. Useful [when creating your own theme](/guide/custom-theme).
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<h1>Custom Layout!</h1>
|
||||
<Content />
|
||||
</template>
|
||||
```
|
||||
|
||||
## `<ClientOnly />` <Badge type="info" text="component" />
|
||||
|
||||
The `<ClientOnly />` component renders its slot only at client side.
|
||||
|
||||
Because VitePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the universal code requirements. In short, make sure to only access Browser / DOM APIs in beforeMount or mounted hooks.
|
||||
|
||||
If you are using or demoing components that are not SSR-friendly (for example, contain custom directives), you can wrap them inside the `ClientOnly` component.
|
||||
|
||||
```vue-html
|
||||
<ClientOnly>
|
||||
<NonSSRFriendlyComponent />
|
||||
</ClientOnly>
|
||||
```
|
||||
|
||||
## `$frontmatter` <Badge type="info" text="template global" />
|
||||
|
||||
Directly access current page's [frontmatter](/guide/frontmatter) data in Vue expressions.
|
||||
|
||||
```md
|
||||
---
|
||||
title: Hello
|
||||
---
|
||||
|
||||
# {{ $frontmatter.title }}
|
||||
```
|
||||
|
||||
## `$params` <Badge type="info" text="template global" />
|
||||
|
||||
Directly access current page's [dynamic route params](/guide/routing#dynamic-routes) in Vue expressions.
|
||||
|
||||
```md
|
||||
- package name: {{ $params.pkg }}
|
||||
- version: {{ $params.version }}
|
||||
```
|
||||
@ -0,0 +1,525 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Site Config
|
||||
|
||||
Site config is where you can define the global settings of the site. App config options define settings that apply to every VitePress site, regardless of what theme it is using. For example, the base directory or the title of the site.
|
||||
|
||||
<div class="site-config-toc">
|
||||
|
||||
[[toc]]
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1280px) {
|
||||
.site-config-toc {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
## Overview
|
||||
|
||||
### Config Resolution
|
||||
|
||||
The config file is always resolved from `<root>/.vitepress/config.[ext]`, where `<root>` is your VitePress [project root](/guide/routing#root-and-source-directory), and `[ext]` is one of the supported file extensions. TypeScript is supported out of the box. Supported extensions include `.js`, `.ts`, `.cjs`, `.mjs`, `.cts`, and `.mts`.
|
||||
|
||||
It is recommended to use ES modules syntax in config files. The config file should default export an object:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
// app level config options
|
||||
lang: 'en-US',
|
||||
title: 'VitePress',
|
||||
description: 'Vite & Vue powered static site generator.',
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Config Intellisense
|
||||
|
||||
Using the `defineConfig` helper will provide TypeScript-powered intellisense for config options. Assuming your IDE supports it, this should work in both JavaScript and TypeScript.
|
||||
|
||||
```js
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### Typed Theme Config
|
||||
|
||||
By default, `defineConfig` helper expects the theme config type from default theme:
|
||||
|
||||
```ts
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
themeConfig: {
|
||||
// Type is `DefaultTheme.Config`
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If you use a custom theme and want type checks for the theme config, you'll need to use `defineConfigWithTheme` instead, and pass the config type for your custom theme via a generic argument:
|
||||
|
||||
```ts
|
||||
import { defineConfigWithTheme } from 'vitepress'
|
||||
import type { ThemeConfig } from 'your-theme'
|
||||
|
||||
export default defineConfigWithTheme<ThemeConfig>({
|
||||
themeConfig: {
|
||||
// Type is `ThemeConfig`
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Site Metadata
|
||||
|
||||
### title
|
||||
|
||||
- Type: `string`
|
||||
- Default: `VitePress`
|
||||
- Can be overridden per page via [frontmatter](./frontmatter-config#title)
|
||||
|
||||
Title for the site. When using the default theme, this will be displayed in the nav bar.
|
||||
|
||||
It will also be used as the default suffix for all individual page titles, unless [`titleTemplate`](#titletemplate) is defined. An individual page's final title will be the text content of its first `<h1>` header, combined with the global `title` as the suffix. For example with the following config and page content:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
title: 'My Awesome Site'
|
||||
}
|
||||
```
|
||||
```md
|
||||
# Hello
|
||||
```
|
||||
|
||||
The title of the page will be `Hello | My Awesome Site`.
|
||||
|
||||
### titleTemplate
|
||||
|
||||
- Type: `string | boolean`
|
||||
- Can be overridden per page via [frontmatter](./frontmatter-config#titletemplate)
|
||||
|
||||
Allows customizing each page's title suffix or the entire title. For example:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
title: 'My Awesome Site',
|
||||
titleTemplate: 'Custom Suffix'
|
||||
}
|
||||
```
|
||||
```md
|
||||
# Hello
|
||||
```
|
||||
|
||||
The title of the page will be `Hello | Custom Suffix`.
|
||||
|
||||
To completely customize how the title should be rendered, you can use the `:title` symbol in `titleTemplate`:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
titleTemplate: ':title - Custom Suffix'
|
||||
}
|
||||
```
|
||||
|
||||
Here `:title` will be replaced with the text inferred from the page's first `<h1>` header. The title of the previous example page will be `Hello - Custom Suffix`.
|
||||
|
||||
The option can be set to `false` to disable title suffixes.
|
||||
|
||||
### description
|
||||
|
||||
- Type: `string`
|
||||
- Default: `A VitePress site`
|
||||
- Can be overridden per page via [frontmatter](./frontmatter-config#description)
|
||||
|
||||
Description for the site. This will render as a `<meta>` tag in the page HTML.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
description: 'A VitePress site'
|
||||
}
|
||||
```
|
||||
|
||||
### head
|
||||
|
||||
- Type: `HeadConfig[]`
|
||||
- Default: `[]`
|
||||
- Can be appended per page via [frontmatter](./frontmatter-config#head)
|
||||
|
||||
Additional elements to render in the `<head>` tag in the page HTML. The user-added tags are rendered before the closing `head` tag, after VitePress tags.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
head: [
|
||||
[
|
||||
'link',
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }
|
||||
]
|
||||
// would render: <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
type HeadConfig =
|
||||
| [string, Record<string, string>]
|
||||
| [string, Record<string, string>, string]
|
||||
```
|
||||
|
||||
### lang
|
||||
|
||||
- Type: `string`
|
||||
- Default: `en-US`
|
||||
|
||||
The lang attribute for the site. This will render as a `<html lang="en-US">` tag in the page HTML.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
lang: 'en-US'
|
||||
}
|
||||
```
|
||||
|
||||
### base
|
||||
|
||||
- Type: `string`
|
||||
- Default: `/`
|
||||
|
||||
The base URL the site will be deployed at. You will need to set this if you plan to deploy your site under a sub path, for example, GitHub pages. If you plan to deploy your site to `https://foo.github.io/bar/`, then you should set base to `'/bar/'`. It should always start and end with a slash.
|
||||
|
||||
The base is automatically prepended to all the URLs that start with / in other options, so you only need to specify it once.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
base: '/base/'
|
||||
}
|
||||
```
|
||||
|
||||
## Routing
|
||||
|
||||
### cleanUrls
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
|
||||
When set to `true`, VitePress will remove the trailing `.html` from URLs. Also see [Generating Clean URL](/guide/routing#generating-clean-url).
|
||||
|
||||
::: warning Server Support Required
|
||||
Enabling this may require additional configuration on your hosting platform. For it to work, your server must be able to serve `/foo.html` when visiting `/foo` **without a redirect**.
|
||||
:::
|
||||
|
||||
### rewrites
|
||||
|
||||
- Type: `Record<string, string>`
|
||||
|
||||
Defines custom directory <-> URL mappings. See [Routing: Route Rewrites](/guide/routing#route-rewrites) for more details.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
rewrites: {
|
||||
'source/:page': 'destination/:page'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Build
|
||||
|
||||
### srcDir
|
||||
|
||||
- Type: `string`
|
||||
- Default: `.`
|
||||
|
||||
The directory where your markdown pages are stored, relative to project root. Also see [Root and Source Directory](/guide/routing#root-and-source-directory).
|
||||
|
||||
```ts
|
||||
export default {
|
||||
srcDir: './src'
|
||||
}
|
||||
```
|
||||
|
||||
### srcExclude
|
||||
|
||||
- Type: `string`
|
||||
- Default: `undefined`
|
||||
|
||||
A [glob pattern](https://github.com/mrmlnc/fast-glob#pattern-syntax) for matching markdown files that should be excluded as source content.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
srcExclude: ['**/README.md', '**/TODO.md']
|
||||
}
|
||||
```
|
||||
|
||||
### outDir
|
||||
|
||||
- Type: `string`
|
||||
- Default: `./.vitepress/dist`
|
||||
|
||||
The build output location for the site, relative to [project root](/guide/routing#root-and-source-directory).
|
||||
|
||||
```ts
|
||||
export default {
|
||||
outDir: '../public'
|
||||
}
|
||||
```
|
||||
|
||||
### cacheDir
|
||||
|
||||
- Type: `string`
|
||||
- Default: `./.vitepress/cache`
|
||||
|
||||
The directory for cache files, relative to [project root](/guide/routing#root-and-source-directory). See also: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir).
|
||||
|
||||
```ts
|
||||
export default {
|
||||
cacheDir: './.vitepress/.vite'
|
||||
}
|
||||
```
|
||||
|
||||
### ignoreDeadLinks
|
||||
|
||||
- Type: `boolean | 'localhostLinks'`
|
||||
- Default: `false`
|
||||
|
||||
When set to `true`, VitePress will not fail builds due to dead links. When set to `'localhostLinks'`, the build will fail on dead links, but won't check `localhost` links.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
ignoreDeadLinks: true
|
||||
}
|
||||
```
|
||||
|
||||
### mpa <Badge type="warning" text="experimental" />
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
|
||||
When set to `true`, the production app will be built in [MAP Mode](/guide/mpa-mode). MPA mode ships 0kb JavaScript by default, at the cost of disabling client-side navigation and requires explicit opt-in for interactivity.
|
||||
|
||||
## Theming
|
||||
|
||||
### appearance
|
||||
|
||||
- Type: `boolean | 'dark'`
|
||||
- Default: `true`
|
||||
|
||||
Whether to enable dark mode (by adding the `.dark` class to the `<html>` element).
|
||||
|
||||
- If the option is set to `true`, the default theme will be determined by the user's preferred color scheme.
|
||||
- If the option is set to `dark`, the theme will be dark by default, unless the user manually toggles it.
|
||||
- If the option is set to `false`, users will not be able to toggle the theme.
|
||||
|
||||
This option injects an inline script that restores users settings from local storage using the `vitepress-theme-appearance` key. This ensures the `.dark` class is applied before the page is rendered to avoid flickering.
|
||||
|
||||
### lastUpdated
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
|
||||
Whether to get the last updated timestamp for each page using Git. The timestamp will be included in each page's page data, accessible via [`useData`](/reference/runtime-api#usedata).
|
||||
|
||||
When using the default theme, enabling this option will display each page's last updated time. You can customize the text via [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) option.
|
||||
|
||||
## Customization
|
||||
|
||||
### markdown
|
||||
|
||||
- Type: `MarkdownOption`
|
||||
|
||||
Configure Markdown parser options. VitePress uses [Markdown-it](https://github.com/markdown-it/markdown-it) as the parser, and [Shiki](https://shiki.matsu.io/) to highlight language syntax. Inside this option, you may pass various Markdown related options to fit your needs.
|
||||
|
||||
```js
|
||||
export default {
|
||||
markdown: {
|
||||
theme: 'material-theme-palenight',
|
||||
lineNumbers: true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Below are all the options that you can have in this object:
|
||||
|
||||
```ts
|
||||
interface MarkdownOptions extends MarkdownIt.Options {
|
||||
// Custom theme for syntax highlighting.
|
||||
// You can use an existing theme.
|
||||
// See: https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes
|
||||
// Or add your own theme.
|
||||
// See: https://github.com/shikijs/shiki/blob/main/docs/themes.md#loading-theme
|
||||
theme?:
|
||||
| Shiki.IThemeRegistration
|
||||
| { light: Shiki.IThemeRegistration; dark: Shiki.IThemeRegistration }
|
||||
|
||||
// Enable line numbers in code block.
|
||||
lineNumbers?: boolean
|
||||
|
||||
// Add support for your own languages.
|
||||
// https://github.com/shikijs/shiki/blob/main/docs/languages.md#supporting-your-own-languages-with-shiki
|
||||
languages?: Shiki.ILanguageRegistration
|
||||
|
||||
// markdown-it-anchor plugin options.
|
||||
// See: https://github.com/valeriangalliat/markdown-it-anchor#usage
|
||||
anchor?: anchorPlugin.AnchorOptions
|
||||
|
||||
// markdown-it-attrs plugin options.
|
||||
// See: https://github.com/arve0/markdown-it-attrs
|
||||
attrs?: {
|
||||
leftDelimiter?: string
|
||||
rightDelimiter?: string
|
||||
allowedAttributes?: string[]
|
||||
disable?: boolean
|
||||
}
|
||||
|
||||
// specify default language for syntax highlighter
|
||||
defaultHighlightLang?: string
|
||||
|
||||
// @mdit-vue/plugin-frontmatter plugin options.
|
||||
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter#options
|
||||
frontmatter?: FrontmatterPluginOptions
|
||||
|
||||
// @mdit-vue/plugin-headers plugin options.
|
||||
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers#options
|
||||
headers?: HeadersPluginOptions
|
||||
|
||||
// @mdit-vue/plugin-sfc plugin options.
|
||||
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-sfc#options
|
||||
sfc?: SfcPluginOptions
|
||||
|
||||
// @mdit-vue/plugin-toc plugin options.
|
||||
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options
|
||||
toc?: TocPluginOptions
|
||||
|
||||
// Configure the Markdown-it instance.
|
||||
config?: (md: MarkdownIt) => void
|
||||
}
|
||||
```
|
||||
|
||||
### vite
|
||||
|
||||
- Type: `import('vite').UserConfig`
|
||||
|
||||
Pass raw [Vite Config](https://vitejs.dev/config/) to internal Vite dev server / bundler.
|
||||
|
||||
### vue
|
||||
|
||||
- Type: `import('@vitejs/plugin-vue').Options`
|
||||
|
||||
Pass raw [`@vitejs/plugin-vue` options](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options) to the internal plugin instance.
|
||||
|
||||
## Build Hooks
|
||||
|
||||
VitePress build hooks allow you to add new functionality and behaviors to your website:
|
||||
|
||||
- Sitemap
|
||||
- Search Indexing
|
||||
- PWA
|
||||
- Teleports
|
||||
|
||||
### buildEnd
|
||||
|
||||
- Type: `(siteConfig: SiteConfig) => Awaitable<void>`
|
||||
|
||||
`buildEnd` is a build CLI hook, it will run after build (SSG) finish but before VitePress CLI process exits.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
async buildEnd(siteConfig) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### postRender
|
||||
|
||||
- Type: `(context: SSGContext) => Awaitable<SSGContext | void>`
|
||||
|
||||
`postRender` is a build hook, called when SSG rendering is done. It will allow you to handle the teleports content during SSG.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
async postRender(context) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
interface SSGContext {
|
||||
content: string
|
||||
teleports?: Record<string, string>
|
||||
[key: string]: any
|
||||
}
|
||||
```
|
||||
|
||||
### transformHead
|
||||
|
||||
- Type: `(context: TransformContext) => Awaitable<HeadConfig[]>`
|
||||
|
||||
`transformHead` is a build hook to transform the head before generating each page. It will allow you to add head entries that cannot be statically added to your VitePress config. You only need to return extra entries, they will be merged automatically with the existing ones.
|
||||
|
||||
::: warning
|
||||
Don't mutate anything inside the `ctx`.
|
||||
:::
|
||||
|
||||
```ts
|
||||
export default {
|
||||
async transformHead(context) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
interface TransformContext {
|
||||
siteConfig: SiteConfig
|
||||
siteData: SiteData
|
||||
pageData: PageData
|
||||
title: string
|
||||
description: string
|
||||
head: HeadConfig[]
|
||||
content: string
|
||||
}
|
||||
```
|
||||
|
||||
### transformHtml
|
||||
|
||||
- Type: `(code: string, id: string, ctx: TransformContext) => Awaitable<string | void>`
|
||||
|
||||
`transformHtml` is a build hook to transform the content of each page before saving to disk.
|
||||
|
||||
::: warning
|
||||
Don't mutate anything inside the `ctx`. Also, modifying the html content may cause hydration problems in runtime.
|
||||
:::
|
||||
|
||||
```ts
|
||||
export default {
|
||||
async transformHtml(code, id, context) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### transformPageData
|
||||
|
||||
- Type: `(pageData: PageData) => Awaitable<Partial<PageData> | { [key: string]: any } | void>`
|
||||
|
||||
`transformPageData` is a hook to transform the `pageData` of each page. You can directly mutate `pageData` or return changed values which will be merged into PageData.
|
||||
|
||||
```ts
|
||||
export default {
|
||||
async transformPageData(pageData) {
|
||||
pageData.contributors = await getPageContributors(pageData.relativePath)
|
||||
}
|
||||
|
||||
// or return data to be merged
|
||||
async transformPageData(pageData) {
|
||||
return {
|
||||
contributors: await getPageContributors(pageData.relativePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Reference in new issue