feat: migrate to shikiji (#3237)

pull/3248/head
Anthony Fu 7 months ago committed by GitHub
parent 46966ac14e
commit 75f18e4733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -163,19 +163,19 @@ describe('Line Numbers', () => {
describe('Import Code Snippets', () => {
test('basic', async () => {
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 () => {
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 () => {
const div = page.locator('#with-other-features + div')
expect(await getClassList(div)).toContain('line-numbers-mode')
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')
})
})
@ -216,10 +216,10 @@ describe('Code Groups', () => {
// blocks
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('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(
await getClassList(blocks.nth(1).locator('code > span').nth(0))
).toContain('highlighted')

@ -13,7 +13,15 @@ export default defineConfig({
cleanUrls: true,
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: {

@ -80,7 +80,7 @@ For more details, see [Frontmatter](../reference/frontmatter-config).
**Input**
```
```md
| Tables | Are | Cool |
| ------------- | :-----------: | ----: |
| col 3 is | right-aligned | $1600 |
@ -265,7 +265,7 @@ Wraps in a <div class="vp-raw">
## 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**
@ -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**
@ -386,7 +386,7 @@ Alternatively, it's possible to highlight directly in the line by using the `//
export default {
data () {
return {
msg: 'Highlighted!' // [!code hl]
msg: 'Highlighted!' // [!!code highlight]
}
}
}
@ -399,7 +399,7 @@ export default {
export default {
data() {
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**
Note that only one space is required after `!code`, here are two to prevent processing.
````
```js
export default {
data () {
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**
Note that only one space is required after `!code`, here are two to prevent processing.
````
```js
export default {
data () {
return {
msg: 'Removed' // [!code --]
msg: 'Added' // [!code ++]
msg: 'Removed' // [!!code --]
msg: 'Added' // [!!code ++]
}
}
}
@ -479,15 +475,13 @@ Adding the `// [!code warning]` or `// [!code error]` comments on a line will co
**Input**
Note that only one space is required after `!code`, here are two to prevent processing.
````
```js
export default {
data () {
return {
msg: 'Error', // [!code error]
msg: 'Warning' // [!code warning]
msg: 'Error', // [!!code error]
msg: 'Warning' // [!!code warning]
}
}
}

@ -454,7 +454,7 @@ When using the default theme, enabling this option will display each page's last
- 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
export default {
@ -462,87 +462,7 @@ export default {
}
```
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?: 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
}
}
```
Check the [type declaration and jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts) for all the options available.
### vite

@ -101,7 +101,8 @@
"mark.js": "8.11.1",
"minisearch": "^6.2.0",
"mrmime": "^1.0.1",
"shiki": "^0.14.5",
"shikiji": "^0.7.2",
"shikiji-transformers": "^0.7.2",
"vite": "^5.0.0",
"vue": "^3.3.8"
},
@ -187,7 +188,6 @@
"rollup-plugin-dts": "^6.1.0",
"rollup-plugin-esbuild": "^6.1.0",
"semver": "^7.5.4",
"shiki-processor": "^0.1.3",
"simple-git-hooks": "^2.9.0",
"sirv": "^2.0.3",
"sitemap": "^7.1.1",

@ -44,9 +44,12 @@ importers:
mrmime:
specifier: ^1.0.1
version: 1.0.1
shiki:
specifier: ^0.14.5
version: 0.14.5
shikiji:
specifier: ^0.7.2
version: 0.7.2
shikiji-transformers:
specifier: ^0.7.2
version: 0.7.2
vite:
specifier: ^5.0.0
version: 5.0.0(@types/node@20.9.1)
@ -261,9 +264,6 @@ importers:
semver:
specifier: ^7.5.4
version: 7.5.4
shiki-processor:
specifier: ^0.1.3
version: 0.1.3(shiki@0.14.5)
simple-git-hooks:
specifier: ^2.9.0
version: 2.9.0
@ -1121,6 +1121,12 @@ packages:
'@types/node': 20.9.1
dev: true
/@types/hast@3.0.3:
resolution: {integrity: sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==}
dependencies:
'@types/unist': 3.0.2
dev: false
/@types/http-errors@2.0.4:
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
dev: true
@ -1180,6 +1186,12 @@ packages:
'@types/linkify-it': 3.0.5
'@types/mdurl': 1.0.5
/@types/mdast@4.0.3:
resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==}
dependencies:
'@types/unist': 3.0.2
dev: false
/@types/mdurl@1.0.5:
resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
@ -1268,10 +1280,18 @@ packages:
resolution: {integrity: sha512-m04Om5Gz6kbjUwAQ7XJJQ30OdEFsSmAVsvn4NYwcTRyMVpKKa1aPuESw1n2CxS5fYkOQv3nHgDKeNa8e76fUkw==}
dev: true
/@types/unist@3.0.2:
resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==}
dev: false
/@types/web-bluetooth@0.0.20:
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
dev: false
/@ungap/structured-clone@1.2.0:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: false
/@vitejs/plugin-vue@4.5.0(vite@5.0.0)(vue@3.3.8):
resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==}
engines: {node: ^14.18.0 || >=16.0.0}
@ -1590,9 +1610,6 @@ packages:
engines: {node: '>=12'}
dev: true
/ansi-sequence-parser@1.1.1:
resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==}
/ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
@ -1761,6 +1778,10 @@ packages:
set-function-length: 1.1.1
dev: true
/ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
dev: false
/chai@4.3.10:
resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==}
engines: {node: '>=4'}
@ -1788,6 +1809,14 @@ packages:
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: true
/character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
dev: false
/character-entities-legacy@3.0.0:
resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
dev: false
/check-error@1.0.3:
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
dependencies:
@ -1884,6 +1913,10 @@ packages:
delayed-stream: 1.0.0
dev: true
/comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
dev: false
/commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
@ -2177,6 +2210,17 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
/dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
dev: false
/devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
dependencies:
dequal: 2.0.3
dev: false
/diff-sequences@29.6.3:
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@ -2244,6 +2288,11 @@ packages:
engines: {node: '>=0.12'}
dev: true
/entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
dev: false
/error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
@ -2681,6 +2730,88 @@ packages:
function-bind: 1.1.2
dev: true
/hast-util-from-parse5@8.0.1:
resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==}
dependencies:
'@types/hast': 3.0.3
'@types/unist': 3.0.2
devlop: 1.1.0
hastscript: 8.0.0
property-information: 6.4.0
vfile: 6.0.1
vfile-location: 5.0.2
web-namespaces: 2.0.1
dev: false
/hast-util-parse-selector@4.0.0:
resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
dependencies:
'@types/hast': 3.0.3
dev: false
/hast-util-raw@9.0.1:
resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==}
dependencies:
'@types/hast': 3.0.3
'@types/unist': 3.0.2
'@ungap/structured-clone': 1.2.0
hast-util-from-parse5: 8.0.1
hast-util-to-parse5: 8.0.0
html-void-elements: 3.0.0
mdast-util-to-hast: 13.0.2
parse5: 7.1.2
unist-util-position: 5.0.0
unist-util-visit: 5.0.0
vfile: 6.0.1
web-namespaces: 2.0.1
zwitch: 2.0.4
dev: false
/hast-util-to-html@9.0.0:
resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==}
dependencies:
'@types/hast': 3.0.3
'@types/unist': 3.0.2
ccount: 2.0.1
comma-separated-tokens: 2.0.3
hast-util-raw: 9.0.1
hast-util-whitespace: 3.0.0
html-void-elements: 3.0.0
mdast-util-to-hast: 13.0.2
property-information: 6.4.0
space-separated-tokens: 2.0.2
stringify-entities: 4.0.3
zwitch: 2.0.4
dev: false
/hast-util-to-parse5@8.0.0:
resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
dependencies:
'@types/hast': 3.0.3
comma-separated-tokens: 2.0.3
devlop: 1.1.0
property-information: 6.4.0
space-separated-tokens: 2.0.2
web-namespaces: 2.0.1
zwitch: 2.0.4
dev: false
/hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
dependencies:
'@types/hast': 3.0.3
dev: false
/hastscript@8.0.0:
resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==}
dependencies:
'@types/hast': 3.0.3
comma-separated-tokens: 2.0.3
hast-util-parse-selector: 4.0.0
property-information: 6.4.0
space-separated-tokens: 2.0.2
dev: false
/he@1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
@ -2697,6 +2828,10 @@ packages:
lru-cache: 10.0.2
dev: true
/html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
dev: false
/htmlparser2@5.0.1:
resolution: {integrity: sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==}
dependencies:
@ -2979,6 +3114,7 @@ packages:
/jsonc-parser@3.2.0:
resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==}
dev: true
/jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
@ -3215,6 +3351,19 @@ packages:
speech-rule-engine: 4.0.7
dev: true
/mdast-util-to-hast@13.0.2:
resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==}
dependencies:
'@types/hast': 3.0.3
'@types/mdast': 4.0.3
'@ungap/structured-clone': 1.2.0
devlop: 1.1.0
micromark-util-sanitize-uri: 2.0.0
trim-lines: 3.0.1
unist-util-position: 5.0.0
unist-util-visit: 5.0.0
dev: false
/mdurl@1.0.1:
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
dev: true
@ -3246,6 +3395,33 @@ packages:
resolution: {integrity: sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==}
dev: true
/micromark-util-character@2.0.1:
resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==}
dependencies:
micromark-util-symbol: 2.0.0
micromark-util-types: 2.0.0
dev: false
/micromark-util-encode@2.0.0:
resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
dev: false
/micromark-util-sanitize-uri@2.0.0:
resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
dependencies:
micromark-util-character: 2.0.1
micromark-util-encode: 2.0.0
micromark-util-symbol: 2.0.0
dev: false
/micromark-util-symbol@2.0.0:
resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
dev: false
/micromark-util-types@2.0.0:
resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
dev: false
/micromatch@4.0.5:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
@ -3542,6 +3718,12 @@ packages:
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
dev: true
/parse5@7.1.2:
resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
dependencies:
entities: 4.5.0
dev: false
/path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
dev: true
@ -3704,6 +3886,10 @@ packages:
sisteransi: 1.0.5
dev: true
/property-information@6.4.0:
resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==}
dev: false
/proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: true
@ -3977,21 +4163,17 @@ packages:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
dev: true
/shiki-processor@0.1.3(shiki@0.14.5):
resolution: {integrity: sha512-oZqVFKweklwt+fj6yUPb+ffrCpYYoJ4RYxNt7w1+aoHetHq5ZaN6oX6+4HrypOi0s/O6A2neBpn+Xf6bM4KfsQ==}
peerDependencies:
shiki: 0.x
/shikiji-transformers@0.7.2:
resolution: {integrity: sha512-Nxg79GL++TvMjprCwhKzXWA4UFTP4fP3jZrkJAkUnSchqV20T2emyy/NgNhNjeX69JoUqTbB82rfVASj5Vec9Q==}
dependencies:
shiki: 0.14.5
dev: true
shikiji: 0.7.2
dev: false
/shiki@0.14.5:
resolution: {integrity: sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==}
/shikiji@0.7.2:
resolution: {integrity: sha512-gOaq7lqi3zSqGm+pMVxDD9NXA6myj5/7s7ZXgJcGdM5eHa49FrUPV46C5nl13rZnN3ZDjEmqF8ZPpNJjXeiBrQ==}
dependencies:
ansi-sequence-parser: 1.1.1
jsonc-parser: 3.2.0
vscode-oniguruma: 1.7.0
vscode-textmate: 8.0.0
hast-util-to-html: 9.0.0
dev: false
/side-channel@1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
@ -4070,6 +4252,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
dev: false
/spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
dependencies:
@ -4188,6 +4374,13 @@ packages:
safe-buffer: 5.2.1
dev: true
/stringify-entities@4.0.3:
resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==}
dependencies:
character-entities-html4: 2.1.0
character-entities-legacy: 3.0.0
dev: false
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@ -4299,6 +4492,10 @@ packages:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: true
/trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
dev: false
/trouter@3.2.1:
resolution: {integrity: sha512-oY3CmIiEYOe1YMEzh++I67lrNOUldtCeuLL0vRPydvQLHZpSJ03B5dgDFlpFsiriMq6e//NDjjopjUzXOztHow==}
engines: {node: '>=6'}
@ -4401,6 +4598,39 @@ packages:
/undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
/unist-util-is@6.0.0:
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
dependencies:
'@types/unist': 3.0.2
dev: false
/unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
dependencies:
'@types/unist': 3.0.2
dev: false
/unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
dependencies:
'@types/unist': 3.0.2
dev: false
/unist-util-visit-parents@6.0.1:
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
dependencies:
'@types/unist': 3.0.2
unist-util-is: 6.0.0
dev: false
/unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
dependencies:
'@types/unist': 3.0.2
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
dev: false
/universalify@2.0.1:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
@ -4427,6 +4657,28 @@ packages:
engines: {node: '>= 0.8'}
dev: true
/vfile-location@5.0.2:
resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==}
dependencies:
'@types/unist': 3.0.2
vfile: 6.0.1
dev: false
/vfile-message@4.0.2:
resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
dependencies:
'@types/unist': 3.0.2
unist-util-stringify-position: 4.0.0
dev: false
/vfile@6.0.1:
resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
dependencies:
'@types/unist': 3.0.2
unist-util-stringify-position: 4.0.0
vfile-message: 4.0.2
dev: false
/vite-node@1.0.0-beta.5(@types/node@20.9.1)(supports-color@9.4.0):
resolution: {integrity: sha512-iXm+GTJbR9R6V/bCM1+LQqIohL/tncZVNGIcTtzpYThBD8yiTkDPvEjy1Mf7KFACtG3qY/0VDMrkuMtqG/JFhg==}
engines: {node: ^18.0.0 || >=20.0.0}
@ -4540,12 +4792,6 @@ packages:
- terser
dev: true
/vscode-oniguruma@1.7.0:
resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==}
/vscode-textmate@8.0.0:
resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
/vue-demi@0.14.6(vue@3.3.8):
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
engines: {node: '>=12'}
@ -4610,6 +4856,10 @@ packages:
- debug
dev: true
/web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
dev: false
/web-resource-inliner@6.0.1:
resolution: {integrity: sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==}
engines: {node: '>=10.0.0'}
@ -4728,3 +4978,7 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
dev: true
/zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
dev: false

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

@ -18,7 +18,6 @@ import MarkdownIt from 'markdown-it'
import anchorPlugin from 'markdown-it-anchor'
import attrsPlugin from 'markdown-it-attrs'
import emojiPlugin from 'markdown-it-emoji'
import type { ILanguageRegistration, IThemeRegistration } from 'shiki'
import type { Logger } from 'vite'
import { containerPlugin, type ContainerOptions } from './plugins/containers'
import { highlight } from './plugins/highlight'
@ -28,36 +27,139 @@ import { lineNumberPlugin } from './plugins/lineNumbers'
import { linkPlugin } from './plugins/link'
import { preWrapperPlugin } from './plugins/preWrapper'
import { snippetPlugin } from './plugins/snippet'
import type {
ThemeRegistration,
BuiltinTheme,
LanguageInput,
ShikijiTransformer
} from 'shikiji'
export type { Header } from '../shared'
export type ThemeOptions =
| IThemeRegistration
| { light: IThemeRegistration; dark: IThemeRegistration }
| ThemeRegistration
| BuiltinTheme
| {
light: ThemeRegistration | BuiltinTheme
dark: ThemeRegistration | BuiltinTheme
}
export interface MarkdownOptions extends MarkdownIt.Options {
lineNumbers?: boolean
/* ==================== General Options ==================== */
/**
* Setup markdown-it instance before applying plugins
*/
preConfig?: (md: MarkdownIt) => void
/**
* Setup markdown-it instance
*/
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
/**
* Options for `markdown-it-attrs`
* @see https://github.com/arve0/markdown-it-attrs
*/
attrs?: {
leftDelimiter?: string
rightDelimiter?: string
allowedAttributes?: Array<string | RegExp>
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
/**
* Options for `@mdit-vue/plugin-headers`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers
*/
headers?: HeadersPluginOptions | boolean
/**
* Options for `@mdit-vue/plugin-sfc`
* @see https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-sfc
*/
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
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
math?: boolean | any
/**
* Options for `markdown-it-container`
* @see https://github.com/markdown-it/markdown-it-container
*/
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
@ -80,7 +182,9 @@ export const createMarkdownRenderer = async (
theme,
options.languages,
options.defaultHighlightLang,
logger
logger,
options.codeTransformers,
options.languageAlias
)),
...options
})

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

@ -4,11 +4,11 @@ This page demonstrates some of the built-in markdown extensions provided by Vite
## 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**
````
````md
```js{4}
export default {
data () {

Loading…
Cancel
Save