Merge branch 'main' into fix-swallowing-error

pull/3201/head
arianrhodsandlot 2 years ago committed by GitHub
commit 6ddd1e8337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,25 @@
# [1.0.0-rc.31](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.30...v1.0.0-rc.31) (2023-11-25)
### Bug Fixes
- **build:** make assets go through vite pipeline during dev too ([#3258](https://github.com/vuejs/vitepress/issues/3258)) ([c3d7f22](https://github.com/vuejs/vitepress/commit/c3d7f22bd313b09e6965ac3125ea662ce283ed2d))
- **theme:** use VPLink for links in VPDocFooter ([#3248](https://github.com/vuejs/vitepress/issues/3248)) ([479a320](https://github.com/vuejs/vitepress/commit/479a320731313b8e7e0bad3f8383ae6bc05ed8e2))
# [1.0.0-rc.30](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.29...v1.0.0-rc.30) (2023-11-23)
### Bug Fixes
- **client:** no onAfterRouteChanged called after popstate ([#3227](https://github.com/vuejs/vitepress/issues/3227)) ([60fc8fd](https://github.com/vuejs/vitepress/commit/60fc8fd24460eede1dc73768ad0aa53616da746f)), closes [#3226](https://github.com/vuejs/vitepress/issues/3226)
- **theme:** remove double padding from sidebar ([ef6d8d1](https://github.com/vuejs/vitepress/commit/ef6d8d1e4295c6ff967c17b5b9c20c04843da5a0)), closes [#3228](https://github.com/vuejs/vitepress/issues/3228)
### Features
- migrate to shikiji ([#3237](https://github.com/vuejs/vitepress/pull/3237)) ([75f18e4](https://github.com/vuejs/vitepress/commit/75f18e47334933b642d14b8b69b372cb1ebd4244))
### BREAKING CHANGES
- VitePress now uses shikiji instead of shiki for syntax highlighting. If you're using features like adding extra languages or custom aliases, please refer [shikiji docs](https://github.com/antfu/shikiji) for migration guide or comment on [#3237](https://github.com/vuejs/vitepress/pull/3237) if you need help.
# [1.0.0-rc.29](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.28...v1.0.0-rc.29) (2023-11-19) # [1.0.0-rc.29](https://github.com/vuejs/vitepress/compare/v1.0.0-rc.28...v1.0.0-rc.29) (2023-11-19)
### Bug Fixes ### Bug Fixes

@ -163,19 +163,19 @@ describe('Line Numbers', () => {
describe('Import Code Snippets', () => { describe('Import Code Snippets', () => {
test('basic', async () => { test('basic', async () => {
const lines = page.locator('#basic-code-snippet + div code > span') const lines = page.locator('#basic-code-snippet + div code > span')
expect(await lines.count()).toBe(22) expect(await lines.count()).toBe(11)
}) })
test('specify region', async () => { test('specify region', async () => {
const lines = page.locator('#specify-region + div code > span') const lines = page.locator('#specify-region + div code > span')
expect(await lines.count()).toBe(6) expect(await lines.count()).toBe(3)
}) })
test('with other features', async () => { test('with other features', async () => {
const div = page.locator('#with-other-features + div') const div = page.locator('#with-other-features + div')
expect(await getClassList(div)).toContain('line-numbers-mode') expect(await getClassList(div)).toContain('line-numbers-mode')
const lines = div.locator('code > span') const lines = div.locator('code > span')
expect(await lines.count()).toBe(6) expect(await lines.count()).toBe(3)
expect(await getClassList(lines.nth(0))).toContain('highlighted') expect(await getClassList(lines.nth(0))).toContain('highlighted')
}) })
}) })
@ -216,10 +216,10 @@ describe('Code Groups', () => {
// blocks // blocks
const blocks = div.locator('.blocks > div') const blocks = div.locator('.blocks > div')
expect(await blocks.nth(0).locator('code > span').count()).toBe(22) expect(await blocks.nth(0).locator('code > span').count()).toBe(11)
expect(await getClassList(blocks.nth(1))).toContain('line-numbers-mode') expect(await getClassList(blocks.nth(1))).toContain('line-numbers-mode')
expect(await getClassList(blocks.nth(1))).toContain('language-ts') expect(await getClassList(blocks.nth(1))).toContain('language-ts')
expect(await blocks.nth(1).locator('code > span').count()).toBe(6) expect(await blocks.nth(1).locator('code > span').count()).toBe(3)
expect( expect(
await getClassList(blocks.nth(1).locator('code > span').nth(0)) await getClassList(blocks.nth(1).locator('code > span').nth(0))
).toContain('highlighted') ).toContain('highlighted')

@ -13,7 +13,15 @@ export default defineConfig({
cleanUrls: true, cleanUrls: true,
markdown: { markdown: {
math: true math: true,
codeTransformers: [
// We use `[!!code` in demo to prevent transformation, here we revert it back.
{
postprocess(code) {
return code.replace(/\[\!\!code/g, '[!code')
}
}
]
}, },
sitemap: { sitemap: {

@ -116,7 +116,7 @@ import DefaultTheme from 'vitepress/theme'
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
async enhanceApp({ app }) { enhanceApp({ app }) {
// register your custom global components // register your custom global components
app.component('MyGlobalComponent' /* ... */) app.component('MyGlobalComponent' /* ... */)
} }

@ -68,7 +68,7 @@ $ npx vitepress init
``` ```
```sh [pnpm] ```sh [pnpm]
$ pnpm dlx vitepress init $ pnpm vitepress init
``` ```
```sh [bun] ```sh [bun]

@ -80,7 +80,7 @@ For more details, see [Frontmatter](../reference/frontmatter-config).
**Input** **Input**
``` ```md
| Tables | Are | Cool | | Tables | Are | Cool |
| ------------- | :-----------: | ----: | | ------------- | :-----------: | ----: |
| col 3 is | right-aligned | $1600 | | col 3 is | right-aligned | $1600 |
@ -265,7 +265,7 @@ Wraps in a <div class="vp-raw">
## Syntax Highlighting in Code Blocks ## Syntax Highlighting in Code Blocks
VitePress uses [Shiki](https://shiki.matsu.io/) 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: VitePress uses [Shikiji](https://github.com/antfu/shikiji) (an improved version of [Shiki](https://shiki.matsu.io/)) 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** **Input**
@ -377,7 +377,7 @@ export default { // Highlighted
} }
``` ```
Alternatively, it's possible to highlight directly in the line by using the `// [!code hl]` comment. Alternatively, it's possible to highlight directly in the line by using the `// [!code hightlight]` comment.
**Input** **Input**
@ -386,7 +386,7 @@ Alternatively, it's possible to highlight directly in the line by using the `//
export default { export default {
data () { data () {
return { return {
msg: 'Highlighted!' // [!code hl] msg: 'Highlighted!' // [!!code highlight]
} }
} }
} }
@ -399,7 +399,7 @@ export default {
export default { export default {
data() { data() {
return { return {
msg: 'Highlighted!' // [!code hl] msg: 'Highlighted!' // [!code highlight]
} }
} }
} }
@ -413,14 +413,12 @@ Additionally, you can define a number of lines to focus using `// [!code focus:<
**Input** **Input**
Note that only one space is required after `!code`, here are two to prevent processing.
```` ````
```js ```js
export default { export default {
data () { data () {
return { return {
msg: 'Focused!' // [!code focus] msg: 'Focused!' // [!!code focus]
} }
} }
} }
@ -445,15 +443,13 @@ Adding the `// [!code --]` or `// [!code ++]` comments on a line will create a d
**Input** **Input**
Note that only one space is required after `!code`, here are two to prevent processing.
```` ````
```js ```js
export default { export default {
data () { data () {
return { return {
msg: 'Removed' // [!code --] msg: 'Removed' // [!!code --]
msg: 'Added' // [!code ++] msg: 'Added' // [!!code ++]
} }
} }
} }
@ -479,15 +475,13 @@ Adding the `// [!code warning]` or `// [!code error]` comments on a line will co
**Input** **Input**
Note that only one space is required after `!code`, here are two to prevent processing.
```` ````
```js ```js
export default { export default {
data () { data () {
return { return {
msg: 'Error', // [!code error] msg: 'Error', // [!!code error]
msg: 'Warning' // [!code warning] msg: 'Warning' // [!!code warning]
} }
} }
} }

@ -58,7 +58,7 @@ export default {
async enhanceApp({ app }) { async enhanceApp({ app }) {
if (!import.meta.env.SSR) { if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import') const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin) app.use(plugin.default)
} }
} }
} }
@ -74,7 +74,7 @@ export default {
async enhanceApp({ app }) { async enhanceApp({ app }) {
if (!import.meta.env.SSR) { if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import') const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin) app.use(plugin.default)
} }
} }
} satisfies Theme } satisfies Theme

@ -454,7 +454,7 @@ When using the default theme, enabling this option will display each page's last
- Type: `MarkdownOption` - 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. Configure Markdown parser options. VitePress uses [Markdown-it](https://github.com/markdown-it/markdown-it) as the parser, and [Shikiji](https://github.com/antfu/shikiji) (an improved version of [Shiki](https://shiki.matsu.io/)) to highlight language syntax. Inside this option, you may pass various Markdown related options to fit your needs.
```js ```js
export default { export default {
@ -462,87 +462,7 @@ export default {
} }
``` ```
Below are all the options that you can have in this object: Check the [type declaration and jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) for all the options available.
```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?: Array<string | RegExp>
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 | boolean
// @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
// @mdit-vue/plugin-component plugin options.
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-component#options
component?: ComponentPluginOptions
// Configure the Markdown-it instance.
config?: (md: MarkdownIt) => void
// Same as `config` but will be applied before all other plugins.
preConfig?: (md: MarkdownIt) => void
// Disable cache (experimental)
cache?: boolean
// Math support (experimental)
// You need to install `markdown-it-mathjax3` and set `math` to `true` to enable it.
// You can also pass options to `markdown-it-mathjax3` here.
// See: https://github.com/tani/markdown-it-mathjax3#customization
math?: boolean | any
// Global custom container titles
container?: {
infoLabel?: string
tipLabel?: string
warningLabel?: string
dangerLabel?: string
detailsLabel?: string
}
}
```
### vite ### vite

@ -1,9 +1,9 @@
{ {
"name": "vitepress", "name": "vitepress",
"version": "1.0.0-rc.29", "version": "1.0.0-rc.31",
"description": "Vite & Vue powered static site generator", "description": "Vite & Vue powered static site generator",
"type": "module", "type": "module",
"packageManager": "pnpm@8.10.5", "packageManager": "pnpm@8.11.0",
"main": "dist/node/index.js", "main": "dist/node/index.js",
"types": "types/index.d.ts", "types": "types/index.d.ts",
"exports": { "exports": {
@ -92,17 +92,18 @@
"dependencies": { "dependencies": {
"@docsearch/css": "^3.5.2", "@docsearch/css": "^3.5.2",
"@docsearch/js": "^3.5.2", "@docsearch/js": "^3.5.2",
"@types/markdown-it": "^13.0.6", "@types/markdown-it": "^13.0.7",
"@vitejs/plugin-vue": "^4.5.0", "@vitejs/plugin-vue": "^4.5.0",
"@vue/devtools-api": "^6.5.1", "@vue/devtools-api": "^6.5.1",
"@vueuse/core": "^10.6.1", "@vueuse/core": "^10.6.1",
"@vueuse/integrations": "^10.6.1", "@vueuse/integrations": "^10.6.1",
"focus-trap": "^7.5.4", "focus-trap": "^7.5.4",
"mark.js": "8.11.1", "mark.js": "8.11.1",
"minisearch": "^6.2.0", "minisearch": "^6.3.0",
"mrmime": "^1.0.1", "mrmime": "^1.0.1",
"shiki": "^0.14.5", "shikiji": "^0.7.4",
"vite": "^5.0.0", "shikiji-transformers": "^0.7.4",
"vite": "^5.0.2",
"vue": "^3.3.8" "vue": "^3.3.8"
}, },
"peerDependencies": { "peerDependencies": {
@ -132,27 +133,27 @@
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-replace": "^5.0.5", "@rollup/plugin-replace": "^5.0.5",
"@types/compression": "^1.7.5", "@types/compression": "^1.7.5",
"@types/cross-spawn": "^6.0.5", "@types/cross-spawn": "^6.0.6",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/escape-html": "^1.0.4", "@types/escape-html": "^1.0.4",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
"@types/lodash.template": "^4.5.3", "@types/lodash.template": "^4.5.3",
"@types/mark.js": "^8.11.11", "@types/mark.js": "^8.11.12",
"@types/markdown-it-attrs": "^4.1.3", "@types/markdown-it-attrs": "^4.1.3",
"@types/markdown-it-container": "^2.0.9", "@types/markdown-it-container": "^2.0.9",
"@types/markdown-it-emoji": "^2.0.4", "@types/markdown-it-emoji": "^2.0.4",
"@types/micromatch": "^4.0.5", "@types/micromatch": "^4.0.6",
"@types/minimist": "^1.2.5", "@types/minimist": "^1.2.5",
"@types/node": "^20.9.1", "@types/node": "^20.10.0",
"@types/postcss-prefix-selector": "^1.16.3", "@types/postcss-prefix-selector": "^1.16.3",
"@types/prompts": "^2.4.8", "@types/prompts": "^2.4.9",
"@vue/shared": "^3.3.8", "@vue/shared": "^3.3.8",
"chokidar": "^3.5.3", "chokidar": "^3.5.3",
"compression": "^1.7.4", "compression": "^1.7.4",
"conventional-changelog-cli": "^4.1.0", "conventional-changelog-cli": "^4.1.0",
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"debug": "^4.3.4", "debug": "^4.3.4",
"esbuild": "^0.19.5", "esbuild": "^0.19.7",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"execa": "^8.0.1", "execa": "^8.0.1",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
@ -161,7 +162,7 @@
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"lint-staged": "^15.1.0", "lint-staged": "^15.1.0",
"lodash.template": "^4.5.0", "lodash.template": "^4.5.0",
"lru-cache": "^10.0.2", "lru-cache": "^10.1.0",
"markdown-it": "^13.0.2", "markdown-it": "^13.0.2",
"markdown-it-anchor": "^8.6.7", "markdown-it-anchor": "^8.6.7",
"markdown-it-attrs": "^4.1.6", "markdown-it-attrs": "^4.1.6",
@ -183,16 +184,15 @@
"prompts": "^2.4.2", "prompts": "^2.4.2",
"punycode": "^2.3.1", "punycode": "^2.3.1",
"rimraf": "^5.0.5", "rimraf": "^5.0.5",
"rollup": "^4.5.0", "rollup": "^4.5.2",
"rollup-plugin-dts": "^6.1.0", "rollup-plugin-dts": "^6.1.0",
"rollup-plugin-esbuild": "^6.1.0", "rollup-plugin-esbuild": "^6.1.0",
"semver": "^7.5.4", "semver": "^7.5.4",
"shiki-processor": "^0.1.3",
"simple-git-hooks": "^2.9.0", "simple-git-hooks": "^2.9.0",
"sirv": "^2.0.3", "sirv": "^2.0.3",
"sitemap": "^7.1.1", "sitemap": "^7.1.1",
"supports-color": "^9.4.0", "supports-color": "^9.4.0",
"typescript": "^5.2.2", "typescript": "^5.3.2",
"vitest": "^1.0.0-beta.4", "vitest": "^1.0.0-beta.4",
"vue-tsc": "^1.8.22", "vue-tsc": "^1.8.22",
"wait-on": "^7.2.0" "wait-on": "^7.2.0"

File diff suppressed because it is too large Load Diff

@ -20,7 +20,8 @@ export const Content = defineComponent({
route.component route.component
? h(route.component, { ? h(route.component, {
onVnodeMounted: runCbs, onVnodeMounted: runCbs,
onVnodeUpdated: runCbs onVnodeUpdated: runCbs,
onVnodeUnmounted: runCbs
}) })
: '404 Page Not Found' : '404 Page Not Found'
] ]

@ -222,11 +222,12 @@ export function createRouter(
{ capture: true } { capture: true }
) )
window.addEventListener('popstate', (e) => { window.addEventListener('popstate', async (e) => {
loadPage( await loadPage(
normalizeHref(location.href), normalizeHref(location.href),
(e.state && e.state.scrollPosition) || 0 (e.state && e.state.scrollPosition) || 0
) )
router.onAfterRouteChanged?.(location.href)
}) })
window.addEventListener('hashchange', (e) => { window.addEventListener('hashchange', (e) => {

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { normalizeLink } from '../support/utils'
import { useEditLink } from '../composables/edit-link' import { useEditLink } from '../composables/edit-link'
import { usePrevNext } from '../composables/prev-next' import { usePrevNext } from '../composables/prev-next'
import VPIconEdit from './icons/VPIconEdit.vue' import VPIconEdit from './icons/VPIconEdit.vue'
@ -43,16 +42,16 @@ const showFooter = computed(() => {
<nav v-if="control.prev?.link || control.next?.link" class="prev-next"> <nav v-if="control.prev?.link || control.next?.link" class="prev-next">
<div class="pager"> <div class="pager">
<a v-if="control.prev?.link" class="pager-link prev" :href="normalizeLink(control.prev.link)"> <VPLink v-if="control.prev?.link" class="pager-link prev" :href="control.prev.link">
<span class="desc" v-html="theme.docFooter?.prev || 'Previous page'"></span> <span class="desc" v-html="theme.docFooter?.prev || 'Previous page'"></span>
<span class="title" v-html="control.prev.text"></span> <span class="title" v-html="control.prev.text"></span>
</a> </VPLink>
</div> </div>
<div class="pager"> <div class="pager">
<a v-if="control.next?.link" class="pager-link next" :href="normalizeLink(control.next.link)"> <VPLink v-if="control.next?.link" class="pager-link next" :href="control.next.link">
<span class="desc" v-html="theme.docFooter?.next || 'Next page'"></span> <span class="desc" v-html="theme.docFooter?.next || 'Next page'"></span>
<span class="title" v-html="control.next.text"></span> <span class="title" v-html="control.next.text"></span>
</a> </VPLink>
</div> </div>
</nav> </nav>
</footer> </footer>

@ -89,7 +89,6 @@ watch(
.VPSidebar { .VPSidebar {
z-index: 1; z-index: 1;
padding-top: var(--vp-nav-height); padding-top: var(--vp-nav-height);
padding-bottom: 128px;
width: var(--vp-sidebar-width); width: var(--vp-sidebar-width);
max-width: 100%; max-width: 100%;
background-color: var(--vp-sidebar-bg-color); background-color: var(--vp-sidebar-bg-color);

@ -1,7 +1,7 @@
.dark .vp-code-light { .dark .vp-code span {
display: none; color: var(--shiki-dark, inherit);
} }
html:not(.dark) .vp-code-dark { html:not(.dark) .vp-code span {
display: none; color: var(--shiki-light, inherit);
} }

@ -18,7 +18,6 @@ import MarkdownIt from 'markdown-it'
import anchorPlugin from 'markdown-it-anchor' import anchorPlugin from 'markdown-it-anchor'
import attrsPlugin from 'markdown-it-attrs' import attrsPlugin from 'markdown-it-attrs'
import emojiPlugin from 'markdown-it-emoji' import emojiPlugin from 'markdown-it-emoji'
import type { ILanguageRegistration, IThemeRegistration } from 'shiki'
import type { Logger } from 'vite' import type { Logger } from 'vite'
import { containerPlugin, type ContainerOptions } from './plugins/containers' import { containerPlugin, type ContainerOptions } from './plugins/containers'
import { highlight } from './plugins/highlight' import { highlight } from './plugins/highlight'
@ -28,36 +27,139 @@ import { lineNumberPlugin } from './plugins/lineNumbers'
import { linkPlugin } from './plugins/link' import { linkPlugin } from './plugins/link'
import { preWrapperPlugin } from './plugins/preWrapper' import { preWrapperPlugin } from './plugins/preWrapper'
import { snippetPlugin } from './plugins/snippet' import { snippetPlugin } from './plugins/snippet'
import type {
ThemeRegistration,
BuiltinTheme,
LanguageInput,
ShikijiTransformer
} from 'shikiji'
export type { Header } from '../shared' export type { Header } from '../shared'
export type ThemeOptions = export type ThemeOptions =
| IThemeRegistration | ThemeRegistration
| { light: IThemeRegistration; dark: IThemeRegistration } | BuiltinTheme
| {
light: ThemeRegistration | BuiltinTheme
dark: ThemeRegistration | BuiltinTheme
}
export interface MarkdownOptions extends MarkdownIt.Options { export interface MarkdownOptions extends MarkdownIt.Options {
lineNumbers?: boolean /* ==================== General Options ==================== */
/**
* Setup markdown-it instance before applying plugins
*/
preConfig?: (md: MarkdownIt) => void preConfig?: (md: MarkdownIt) => void
/**
* Setup markdown-it instance
*/
config?: (md: MarkdownIt) => void config?: (md: MarkdownIt) => void
/**
* Disable cache (experimental)
*/
cache?: boolean
externalLinks?: Record<string, string>
/* ==================== Syntax Highlighting ==================== */
/**
* Custom theme for syntax highlighting.
*
* You can also pass an object with `light` and `dark` themes to support dual themes.
*
* @example { theme: 'github-dark' }
* @example { theme: { light: 'github-light', dark: 'github-dark' } }
*
* You can use an existing theme.
* @see https://github.com/antfu/shikiji/blob/main/docs/themes.md#all-themes
* Or add your own theme.
* @see https://github.com/antfu/shikiji/blob/main/docs/themes.md#load-custom-themes
*/
theme?: ThemeOptions
/**
* Languages for syntax highlighting.
* @see https://github.com/antfu/shikiji/blob/main/docs/languages.md#all-themes
*/
languages?: LanguageInput[]
/**
* Custom language aliases.
*
* @example { 'my-lang': 'js' }
* @see https://github.com/antfu/shikiji/tree/main#custom-language-aliases
*/
languageAlias?: Record<string, string>
/**
* Show line numbers in code blocks
* @default false
*/
lineNumbers?: boolean
/**
* Fallback language when the specified language is not available.
*/
defaultHighlightLang?: string
/**
* Transformers applied to code blocks
* @see https://github.com/antfu/shikiji#hast-transformers
*/
codeTransformers?: ShikijiTransformer[]
/* ==================== Markdown It Plugins ==================== */
/**
* Options for `markdown-it-anchor`
* @see https://github.com/valeriangalliat/markdown-it-anchor
*/
anchor?: anchorPlugin.AnchorOptions anchor?: anchorPlugin.AnchorOptions
/**
* Options for `markdown-it-attrs`
* @see https://github.com/arve0/markdown-it-attrs
*/
attrs?: { attrs?: {
leftDelimiter?: string leftDelimiter?: string
rightDelimiter?: string rightDelimiter?: string
allowedAttributes?: Array<string | RegExp> allowedAttributes?: Array<string | RegExp>
disable?: boolean disable?: boolean
} }
defaultHighlightLang?: string /**
* Options for `@mdit-vue/plugin-frontmatter`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter
*/
frontmatter?: FrontmatterPluginOptions frontmatter?: FrontmatterPluginOptions
/**
* Options for `@mdit-vue/plugin-headers`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers
*/
headers?: HeadersPluginOptions | boolean headers?: HeadersPluginOptions | boolean
/**
* Options for `@mdit-vue/plugin-sfc`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-sfc
*/
sfc?: SfcPluginOptions sfc?: SfcPluginOptions
theme?: ThemeOptions /**
languages?: ILanguageRegistration[] * Options for `@mdit-vue/plugin-toc`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc
*/
toc?: TocPluginOptions toc?: TocPluginOptions
externalLinks?: Record<string, string> /**
cache?: boolean * Options for `@mdit-vue/plugin-component`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-component
*/
component?: ComponentPluginOptions component?: ComponentPluginOptions
math?: boolean | any /**
* Options for `markdown-it-container`
* @see https://github.com/markdown-it/markdown-it-container
*/
container?: ContainerOptions container?: ContainerOptions
/**
* Math support (experimental)
*
* You need to install `markdown-it-mathjax3` and set `math` to `true` to enable it.
* You can also pass options to `markdown-it-mathjax3` here.
* @default false
* @see https://vitepress.dev/guide/markdown#math-equations
*/
math?: boolean | any
} }
export type MarkdownRenderer = MarkdownIt export type MarkdownRenderer = MarkdownIt
@ -80,7 +182,9 @@ export const createMarkdownRenderer = async (
theme, theme,
options.languages, options.languages,
options.defaultHighlightLang, options.defaultHighlightLang,
logger logger,
options.codeTransformers,
options.languageAlias
)), )),
...options ...options
}) })

@ -1,23 +1,23 @@
import { customAlphabet } from 'nanoid' import { customAlphabet } from 'nanoid'
import c from 'picocolors' import c from 'picocolors'
import type { LanguageInput, ShikijiTransformer } from 'shikiji'
import { import {
BUNDLED_LANGUAGES, bundledLanguages,
type HtmlRendererOptions,
type ILanguageRegistration,
type IThemeRegistration
} from 'shiki'
import {
addClass,
createDiffProcessor,
createFocusProcessor,
createHighlightProcessor,
createRangeProcessor,
defineProcessor,
getHighlighter, getHighlighter,
type Processor addClassToHast,
} from 'shiki-processor' isPlaintext as isPlainLang,
isSpecialLang
} from 'shikiji'
import type { Logger } from 'vite' import type { Logger } from 'vite'
import type { ThemeOptions } from '../markdown' import type { ThemeOptions } from '../markdown'
import {
transformerCompactLineOptions,
transformerNotationDiff,
transformerNotationErrorLevel,
transformerNotationFocus,
transformerNotationHighlight,
type TransformerCompactLineOption
} from 'shikiji-transformers'
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10) const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
@ -29,7 +29,7 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
* 2. convert line numbers into line options: * 2. convert line numbers into line options:
* [{ line: number, classes: string[] }] * [{ line: number, classes: string[] }]
*/ */
const attrsToLines = (attrs: string): HtmlRendererOptions['lineOptions'] => { const attrsToLines = (attrs: string): TransformerCompactLineOption[] => {
attrs = attrs.replace(/^(?:\[.*?\])?.*?([\d,-]+).*/, '$1').trim() attrs = attrs.replace(/^(?:\[.*?\])?.*?([\d,-]+).*/, '$1').trim()
const result: number[] = [] const result: number[] = []
if (!attrs) { if (!attrs) {
@ -53,37 +53,38 @@ const attrsToLines = (attrs: string): HtmlRendererOptions['lineOptions'] => {
})) }))
} }
const errorLevelProcessor = defineProcessor({
name: 'error-level',
handler: createRangeProcessor({
error: ['highlighted', 'error'],
warning: ['highlighted', 'warning']
})
})
export async function highlight( export async function highlight(
theme: ThemeOptions, theme: ThemeOptions,
languages: ILanguageRegistration[] = [], languages: LanguageInput[] = [],
defaultLang: string = '', defaultLang: string = '',
logger: Pick<Logger, 'warn'> = console logger: Pick<Logger, 'warn'> = console,
userTransformers: ShikijiTransformer[] = [],
languageAlias: Record<string, string> = {}
): Promise<(str: string, lang: string, attrs: string) => string> { ): Promise<(str: string, lang: string, attrs: string) => string> {
const hasSingleTheme = typeof theme === 'string' || 'name' in theme
const getThemeName = (themeValue: IThemeRegistration) =>
typeof themeValue === 'string' ? themeValue : themeValue.name
const processors: Processor[] = [
createFocusProcessor(),
createHighlightProcessor({ hasHighlightClass: 'highlighted' }),
createDiffProcessor(),
errorLevelProcessor
]
const highlighter = await getHighlighter({ const highlighter = await getHighlighter({
themes: hasSingleTheme ? [theme] : [theme.dark, theme.light], themes:
langs: [...BUNDLED_LANGUAGES, ...languages], typeof theme === 'string' || 'name' in theme
processors ? [theme]
: [theme.light, theme.dark],
langs: [...Object.keys(bundledLanguages), ...languages],
langAlias: languageAlias
}) })
const transformers: ShikijiTransformer[] = [
transformerNotationDiff(),
transformerNotationFocus({
classActiveLine: 'has-focus',
classActivePre: 'has-focused-lines'
}),
transformerNotationHighlight(),
transformerNotationErrorLevel(),
{
pre(node) {
addClassToHast(node, 'vp-code')
}
}
]
const styleRE = /<pre[^>]*(style=".*?")/ const styleRE = /<pre[^>]*(style=".*?")/
const preRE = /^<pre(.*?)>/ const preRE = /^<pre(.*?)>/
const vueRE = /-vue$/ const vueRE = /-vue$/
@ -102,7 +103,7 @@ export async function highlight(
if (lang) { if (lang) {
const langLoaded = highlighter.getLoadedLanguages().includes(lang as any) const langLoaded = highlighter.getLoadedLanguages().includes(lang as any)
if (!langLoaded && !['ansi', 'plaintext', 'txt', 'text'].includes(lang)) { if (!langLoaded && !isPlainLang(lang) && !isSpecialLang(lang)) {
logger.warn( logger.warn(
c.yellow( c.yellow(
`\nThe language '${lang}' is not loaded, falling back to '${ `\nThe language '${lang}' is not loaded, falling back to '${
@ -155,24 +156,21 @@ export async function highlight(
str = removeMustache(str).trimEnd() str = removeMustache(str).trimEnd()
const codeToHtml = (theme: IThemeRegistration) => { const highlighted = highlighter.codeToHtml(str, {
const res = lang,
lang === 'ansi' transformers: [
? highlighter.ansiToHtml(str, { ...transformers,
lineOptions, transformerCompactLineOptions(lineOptions),
theme: getThemeName(theme) ...userTransformers
}) ],
: highlighter.codeToHtml(str, { ...(typeof theme === 'string' || 'name' in theme
lang, ? { theme }
lineOptions, : {
theme: getThemeName(theme) themes: theme,
}) defaultColor: false
return fillEmptyHighlightedLine(cleanup(restoreMustache(res))) })
} })
if (hasSingleTheme) return codeToHtml(theme) return fillEmptyHighlightedLine(cleanup(restoreMustache(highlighted)))
const dark = addClass(codeToHtml(theme.dark), 'vp-code-dark', 'pre')
const light = addClass(codeToHtml(theme.light), 'vp-code-light', 'pre')
return dark + light
} }
} }

@ -95,6 +95,22 @@ export async function createVitePressPlugin(
} }
} }
const getMergedAssetUrlOptions = () => {
const { transformAssetUrls } = userVuePluginOptions?.template ?? {}
const assetUrlOptions = { includeAbsolute: true }
if (transformAssetUrls && typeof transformAssetUrls === 'object') {
// presence of array fields means this is raw tags config
if (Object.values(transformAssetUrls).some((val) => Array.isArray(val))) {
return { ...assetUrlOptions, tags: transformAssetUrls as any }
} else {
return { ...assetUrlOptions, ...transformAssetUrls }
}
} else {
return assetUrlOptions
}
}
// lazy require plugin-vue to respect NODE_ENV in @vue/compiler-x // lazy require plugin-vue to respect NODE_ENV in @vue/compiler-x
const vuePlugin = await import('@vitejs/plugin-vue').then((r) => const vuePlugin = await import('@vitejs/plugin-vue').then((r) =>
r.default({ r.default({
@ -105,7 +121,8 @@ export async function createVitePressPlugin(
compilerOptions: { compilerOptions: {
...userVuePluginOptions?.template?.compilerOptions, ...userVuePluginOptions?.template?.compilerOptions,
isCustomElement isCustomElement
} },
transformAssetUrls: getMergedAssetUrlOptions()
} }
}) })
) )

@ -4,11 +4,11 @@ This page demonstrates some of the built-in markdown extensions provided by Vite
## Syntax Highlighting ## Syntax Highlighting
VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting: VitePress provides Syntax Highlighting powered by [Shikiji](https://github.com/antfu/shikiji), with additional features like line-highlighting:
**Input** **Input**
```` ````md
```js{4} ```js{4}
export default { export default {
data () { data () {

Loading…
Cancel
Save