# Markdown Extensions VitePress comes with built in Markdown Extensions. ## Header Anchors Headers automatically get anchor links applied. Rendering of anchors can be configured using the `markdown.anchor` option. ### Custom anchors To specify a custom anchor tag for a heading instead of using the auto-generated one, add a suffix to the heading: ``` # Using custom anchors {#my-anchor} ``` This allows you to link to the heading as `#my-anchor` instead of the default `#using-custom-anchors`. ## Links Both internal and external links get special treatment. ### Internal Links Internal links are converted to router link for SPA navigation. Also, every `index.md` contained in each sub-directory will automatically be converted to `index.html`, with corresponding URL `/`. For example, given the following directory structure: ``` . ├─ index.md ├─ foo │ ├─ index.md │ ├─ one.md │ └─ two.md └─ bar ├─ index.md ├─ three.md └─ four.md ``` And providing you are in `foo/one.md`: ```md [Home](/) [foo](/foo/) [foo heading](./#heading) [bar - three](../bar/three) [bar - three](../bar/three.md) [bar - four](../bar/four.html) ``` ### Page Suffix Pages and internal links get generated with the `.html` suffix by default. ### External Links Outbound links automatically get `target="_blank" rel="noreferrer"`: - [vuejs.org](https://vuejs.org) - [VitePress on GitHub](https://github.com/vuejs/vitepress) ## Frontmatter [YAML frontmatter](https://jekyllrb.com/docs/front-matter/) is supported out of the box: ```yaml --- title: Blogging Like a Hacker lang: en-US --- ``` This data will be available to the rest of the page, along with all custom and theming components. For more details, see [Frontmatter](../reference/frontmatter-config). ## GitHub-Style Tables **Input** ```md | Tables | Are | Cool | | ------------- | :-----------: | ----: | | col 3 is | right-aligned | $1600 | | col 2 is | centered | $12 | | zebra stripes | are neat | $1 | ``` **Output** | Tables | Are | Cool | | ------------- | :-----------: | -----: | | col 3 is | right-aligned | \$1600 | | col 2 is | centered | \$12 | | zebra stripes | are neat | \$1 | ## Emoji :tada: **Input** ``` :tada: :100: ``` **Output** :tada: :100: A [list of all emojis](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs) is available. ## Table of Contents **Input** ``` [[toc]] ``` **Output** [[toc]] Rendering of the TOC can be configured using the `markdown.toc` option. ## Custom Containers Custom containers can be defined by their types, titles, and contents. ### Default Title **Input** ```md ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ``` **Output** ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ### Custom Title You may set custom title by appending the text right after the "type" of the container. **Input** ````md ::: danger STOP Danger zone, do not proceed ::: ::: details Click me to toggle the code ```js console.log('Hello, VitePress!') ``` ::: ```` **Output** ::: danger STOP Danger zone, do not proceed ::: ::: details Click me to toggle the code ```js console.log('Hello, VitePress!') ``` ::: Also, you may set custom titles globally by adding the following content in site config, helpful if not writing in English: ```ts // config.ts export default defineConfig({ // ... markdown: { container: { tipLabel: '提示', warningLabel: '警告', dangerLabel: '危险', infoLabel: '信息', detailsLabel: '详细信息' } } // ... }) ``` ### Additional Attributes You can add additional attributes to the custom containers. We use [markdown-it-attrs](https://github.com/arve0/markdown-it-attrs) for this feature, and it is supported on almost all markdown elements. For example, you can set the `open` attribute to make the details block open by default: **Input** ````md ::: details Click me to toggle the code {open} ```js console.log('Hello, VitePress!') ``` ::: ```` **Output** ::: details Click me to toggle the code {open} ```js console.log('Hello, VitePress!') ``` ::: ### `raw` This is a special container that can be used to prevent style and router conflicts with VitePress. This is especially useful when you're documenting component libraries. You might also wanna check out [whyframe](https://whyframe.dev/docs/integrations/vitepress) for better isolation. **Syntax** ```md ::: raw Wraps in a
::: ``` `vp-raw` class can be directly used on elements too. Style isolation is currently opt-in: - Install `postcss` with your preferred package manager: ```sh $ npm add -D postcss ``` - Create a file named `docs/postcss.config.mjs` and add this to it: ```js import { postcssIsolateStyles } from 'vitepress' export default { plugins: [postcssIsolateStyles()] } ``` It uses [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector) under the hood. You can pass its options like this: ```js postcssIsolateStyles({ includeFiles: [/vp-doc\.css/] // defaults to /base\.css/ }) ``` ## GitHub-flavored Alerts VitePress also supports [GitHub-flavored alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) to render as callouts. They will be rendered the same as the [custom containers](#custom-containers). ```md > [!NOTE] > Highlights information that users should take into account, even when skimming. > [!TIP] > Optional information to help a user be more successful. > [!IMPORTANT] > Crucial information necessary for users to succeed. > [!WARNING] > Critical content demanding immediate user attention due to potential risks. > [!CAUTION] > Negative potential consequences of an action. ``` > [!NOTE] > Highlights information that users should take into account, even when skimming. > [!TIP] > Optional information to help a user be more successful. > [!IMPORTANT] > Crucial information necessary for users to succeed. > [!WARNING] > Critical content demanding immediate user attention due to potential risks. > [!CAUTION] > Negative potential consequences of an action. ## Syntax Highlighting in Code Blocks VitePress uses [Shiki](https://github.com/shikijs/shiki) to highlight language syntax in Markdown code blocks, using coloured text. Shiki supports a wide variety of programming languages. All you need to do is append a valid language alias to the beginning backticks for the code block: **Input** ```` ```js export default { name: 'MyComponent', // ... } ``` ```` ```` ```html ``` ```` **Output** ```js export default { name: 'MyComponent' // ... } ``` ```html ``` A [list of valid languages](https://shiki.style/languages) is available on Shiki's repository. You may also customize syntax highlight theme in app config. Please see [`markdown` options](../reference/site-config#markdown) for more details. ## Line Highlighting in Code Blocks **Input** ```` ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` ```` **Output** ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` In addition to a single line, you can also specify multiple single lines, ranges, or both: - Line ranges: for example `{5-8}`, `{3-10}`, `{10-17}` - Multiple single lines: for example `{4,7,9}` - Line ranges and single lines: for example `{4,7-13,16,23-27,40}` **Input** ```` ```js{1,4,6-8} export default { // Highlighted data () { return { msg: `Highlighted! This line isn't highlighted, but this and the next 2 are.`, motd: 'VitePress is awesome', lorem: 'ipsum' } } } ``` ```` **Output** ```js{1,4,6-8} export default { // Highlighted data () { return { msg: `Highlighted! This line isn't highlighted, but this and the next 2 are.`, motd: 'VitePress is awesome', lorem: 'ipsum', } } } ``` Alternatively, it's possible to highlight directly in the line by using the `// [!code highlight]` comment. **Input** ```` ```js export default { data () { return { msg: 'Highlighted!' // [!!code highlight] } } } ``` ```` **Output** ```js export default { data() { return { msg: 'Highlighted!' // [!code highlight] } } } ``` ## Focus in Code Blocks Adding the `// [!code focus]` comment on a line will focus it and blur the other parts of the code. Additionally, you can define a number of lines to focus using `// [!code focus:]`. **Input** ```` ```js export default { data () { return { msg: 'Focused!' // [!!code focus] } } } ``` ```` **Output** ```js export default { data() { return { msg: 'Focused!' // [!code focus] } } } ``` ## Colored Diffs in Code Blocks Adding the `// [!code --]` or `// [!code ++]` comments on a line will create a diff of that line, while keeping the colors of the codeblock. **Input** ```` ```js export default { data () { return { msg: 'Removed' // [!!code --] msg: 'Added' // [!!code ++] } } } ``` ```` **Output** ```js export default { data () { return { msg: 'Removed' // [!code --] msg: 'Added' // [!code ++] } } } ``` ## Errors and Warnings in Code Blocks Adding the `// [!code warning]` or `// [!code error]` comments on a line will color it accordingly. **Input** ```` ```js export default { data () { return { msg: 'Error', // [!!code error] msg: 'Warning' // [!!code warning] } } } ``` ```` **Output** ```js export default { data() { return { msg: 'Error', // [!code error] msg: 'Warning' // [!code warning] } } } ``` ## Line Numbers You can enable line numbers for each code blocks via config: ```js export default { markdown: { lineNumbers: true } } ``` Please see [`markdown` options](../reference/site-config#markdown) for more details. You can add `:line-numbers` / `:no-line-numbers` mark in your fenced code blocks to override the value set in config. You can also customize the starting line number by adding `=` after `:line-numbers`. For example, `:line-numbers=2` means the line numbers in code blocks will start from `2`. **Input** ````md ```ts {1} // line-numbers is disabled by default const line2 = 'This is line 2' const line3 = 'This is line 3' ``` ```ts:line-numbers {1} // line-numbers is enabled const line2 = 'This is line 2' const line3 = 'This is line 3' ``` ```ts:line-numbers=2 {1} // line-numbers is enabled and start from 2 const line3 = 'This is line 3' const line4 = 'This is line 4' ``` ```` **Output** ```ts {1} // line-numbers is disabled by default const line2 = 'This is line 2' const line3 = 'This is line 3' ``` ```ts:line-numbers {1} // line-numbers is enabled const line2 = 'This is line 2' const line3 = 'This is line 3' ``` ```ts:line-numbers=2 {1} // line-numbers is enabled and start from 2 const line3 = 'This is line 3' const line4 = 'This is line 4' ``` ## Import Code Snippets You can import code snippets from existing files via following syntax: ```md <<< @/filepath ``` It also supports [line highlighting](#line-highlighting-in-code-blocks): ```md <<< @/filepath{highlightLines} ``` **Input** ```md <<< @/snippets/snippet.js{2} ``` **Code file** <<< @/snippets/snippet.js **Output** <<< @/snippets/snippet.js{2} ::: tip The value of `@` corresponds to the source root. By default it's the VitePress project root, unless `srcDir` is configured. Alternatively, you can also import from relative paths: ```md <<< ../snippets/snippet.js ``` ::: You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/codebasics#_folding) to only include the corresponding part of the code file. You can provide a custom region name after a `#` following the filepath: **Input** ```md <<< @/snippets/snippet-with-region.js#snippet{1} ``` **Code file** <<< @/snippets/snippet-with-region.js **Output** <<< @/snippets/snippet-with-region.js#snippet{1} You can also specify the language inside the braces (`{}`) like this: ```md <<< @/snippets/snippet.cs{c#} <<< @/snippets/snippet.cs{1,2,4-6 c#} <<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers} ``` This is helpful if source language cannot be inferred from your file extension. ## Code Groups You can group multiple code blocks like this: **Input** ````md ::: code-group ```js [config.js] /** * @type {import('vitepress').UserConfig} */ const config = { // ... } export default config ``` ```ts [config.ts] import type { UserConfig } from 'vitepress' const config: UserConfig = { // ... } export default config ``` ::: ```` **Output** ::: code-group ```js [config.js] /** * @type {import('vitepress').UserConfig} */ const config = { // ... } export default config ``` ```ts [config.ts] import type { UserConfig } from 'vitepress' const config: UserConfig = { // ... } export default config ``` ::: You can also [import snippets](#import-code-snippets) in code groups: **Input** ```md ::: code-group <<< @/snippets/snippet.js <<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] ::: ``` **Output** ::: code-group <<< @/snippets/snippet.js <<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region] ::: ## Markdown File Inclusion You can include a markdown file in another markdown file, even nested. ::: tip You can also prefix the markdown path with `@`, it will act as the source root. By default, it's the VitePress project root, unless `srcDir` is configured. ::: For example, you can include a relative markdown file using this: **Input** ```md # Docs ## Basics ``` **Part file** (`parts/basics.md`) ```md Some getting started stuff. ### Configuration Can be created using `.foorc.json`. ``` **Equivalent code** ```md # Docs ## Basics Some getting started stuff. ### Configuration Can be created using `.foorc.json`. ``` It also supports selecting a line range: **Input** ```md # Docs ## Basics ``` **Part file** (`parts/basics.md`) ```md Some getting started stuff. ### Configuration Can be created using `.foorc.json`. ``` **Equivalent code** ```md # Docs ## Basics ### Configuration Can be created using `.foorc.json`. ``` The format of the selected line range can be: `{3,}`, `{,10}`, `{1,10}` You can also use a [VS Code region](https://code.visualstudio.com/docs/editor/codebasics#_folding) to only include the corresponding part of the code file. You can provide a custom region name after a `#` following the filepath: **Input** ```md # Docs ## Basics ``` **Part file** (`parts/basics.md`) ```md ## Usage Line 1 ## Usage Line 2 ## Usage Line 3 ``` **Equivalent code** ```md # Docs ## Basics ## Usage Line 1 ## Usage Line 3 ``` ::: warning Note that this does not throw errors if your file is not present. Hence, when using this feature make sure that the contents are being rendered as expected. ::: ## Math Equations This is currently opt-in. To enable it, you need to install `markdown-it-mathjax3` and set `markdown.math` to `true` in your config file: ```sh npm add -D markdown-it-mathjax3 ``` ```ts // .vitepress/config.ts export default { markdown: { math: true } } ``` **Input** ```md When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | ``` **Output** When $a \ne 0$, there are two solutions to $(ax^2 + bx + c = 0)$ and they are $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$ **Maxwell's equations:** | equation | description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | $\nabla \cdot \vec{\mathbf{B}} = 0$ | divergence of $\vec{\mathbf{B}}$ is zero | | $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | curl of $\vec{\mathbf{E}}$ is proportional to the rate of change of $\vec{\mathbf{B}}$ | | $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ | ## Image Lazy Loading You can enable lazy loading for each image added via markdown by setting `lazyLoading` to `true` in your config file: ```js export default { markdown: { image: { // image lazy loading is disabled by default lazyLoading: true } } } ``` ## Advanced Configuration VitePress uses [markdown-it](https://github.com/markdown-it/markdown-it) as the Markdown renderer. A lot of the extensions above are implemented via custom plugins. You can further customize the `markdown-it` instance using the `markdown` option in `.vitepress/config.js`: ```js import { defineConfig } from 'vitepress' import markdownItAnchor from 'markdown-it-anchor' import markdownItFoo from 'markdown-it-foo' export default defineConfig({ markdown: { // options for markdown-it-anchor // https://github.com/valeriangalliat/markdown-it-anchor#usage anchor: { permalink: markdownItAnchor.permalink.headerLink() }, // options for @mdit-vue/plugin-toc // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options toc: { level: [1, 2] }, config: (md) => { // use more markdown-it plugins! md.use(markdownItFoo) } } }) ``` See full list of configurable properties in [Config Reference: App Config](../reference/site-config#markdown).