最近在使用 VitePress 搭建技术文档网站,遇到了一个小问题。虽然 VitePress 的 Markdown 代码块支持非常多语言的语法高亮,但我们的文档中存在许多 DSL(领域特定语言)代码,这些代码没有现成的语言能够适配,只能以纯文本(Plain Text)样式显示,导致阅读起来非常不直观。因此,我决定为 VitePress 添加自定义的语言进行语法高亮,来改善这种情况。
通过阅读 VitePress 的文档 Syntax Highlighting in Code Blocks,我了解到它使用了 markdown-it 进行 Markdown 解析,并通过 Shiki 实现了代码块的语法高亮。不过,在我搜寻了一番 VitePress 的文档后,最终也没有找到有关于添加自定义语言进行语法高亮的具体说明。看来这个只能自己摸索了。
VitePress 文档中有提到可以通过配置 markdown 选项来自定义语法高亮的主题,我顺着查看了 jsdocs ,发现除了可以配置主题外,还有一个 shikiSetup
选项,可以用来自定义 Shiki 的 Highlighter 配置。
/**
* Setup Shiki instance
*/
shikiSetup?: (shiki: Highlighter) => void | Promise<void>
接下来,我又查看了 Shiki 的文档 Load Custom Languages,得知 Highlighter
有一个 loadLanguage
方法,可以用来加载自定义语言。于是,我就有了具体的实现思路。
实现步骤
下面通过一个简单的例子来具体说明如何为 VitePress 添加自定义语言进行代码高亮。
Shiki 是基于 TextMate 的语法,如果我们要自定义语言的语法高亮,就需要先编写一个 TextMate 语法文件。先在 .vitepress
目录下创建一个名为 my-lang.js
文件,内容如下:
export default {
"displayName": "UP",
"name": "up",
"scopeName": "source.up",
"patterns": [
{
"match": "^\\s*(package|module)\\b",
"name": "keyword.up"
},
{
"begin": "<",
"end": ">",
"name": "comment.block.angle.up",
"contentName": "string.quoted.angle.up"
},
{
"match": "//.*",
"name": "comment.line.double-slash.up"
}
]
}
其中 name
是语言的标识符,也是对应 Markdown 代码块声明起始三个反引号后的语言标识符。
然后在 VitePress 的配置文件 config.mts
中配置 shikiSetup
选项,加载自定义语言(其实就是一个 JavaScript 对象,通过解析前面编写的 JSON 文件得到):
import {defineConfig} from "vitepress";
import myLang from "./my-lang";
// https://vitepress.dev/reference/site-config
export default defineConfig({
// ...
markdown: {
async shikiSetup(highlighter) {
await highlighter.loadLanguage([myLang]);
}
},
})
最后,就可以在 Markdown 中指定对应的语言名 up
使用自定义的语言进行代码高亮了:
```up
project your.package.name
// this is a comment
module platform <平台>
module app <应用>
module user <用户>
```
下面是展示效果截图:
进一步阅读
- 关于语法规则的编写,可以参考 TextMate Manual。
- 关于 Shiki 的更多用法,可以参考 Shiki。
- 关于 VitePress 的更多用法,可以参考 VitePress。