搜索博客与维基

技术/前端/样式

Shiki

Astro 内置的语法高亮引擎,构建时同时生成浅色和深色两套配色,切主题不闪。

1 分钟阅读别名:shiki、语法高亮

Shiki 是 Astro 内置的语法高亮引擎。它和高亮库的常见做法有个根本区别:在构建阶段把代码切成带颜色的 HTML 片段,而不是在浏览器里跑解析器。

双主题是怎么工作的

配置是这样:

shikiConfig: {
  themes: { light: 'github-light', dark: 'github-dark-dimmed' },
  defaultColor: false,
}

defaultColor: false 是关键。它让 Shiki 把两套配色都写成 CSS 变量,同时挂在代码块上:

<pre class="astro-code" style="--shiki-light:#24292e; --shiki-dark:#adbac7;">

然后样式表按当前主题二选一。结果是切换深色模式不需要重新下载任何东西,也不会有颜色闪一下。

行号与高亮行

Astro 的代码围栏可以带额外参数:

```ts title="src/app.ts" showLineNumbers {3,7-9}

这些参数由自定义的 transformer 解析:

写法效果
title="..."代码块上方显示一条文件名栏
showLineNumbers 或 ln左侧显示行号
{3,7-9}指定行加高亮底色

实现的关键是 transformer 提供两个钩子:pre(node) 处理整个代码块,line(node, lineNumber) 逐行处理。只在 pre 里做行高亮是个典型错误,因为那个钩子拿不到每一行。

为什么不引第三方高亮库

Astro 自带 Shiki,额外装 highlight.js 或 Prism 只是多一份需要维护的依赖,还多一份样式要覆盖。少一个依赖,少一类问题。

代价

因为高亮发生在构建阶段,构建产物里每种语言都会多出一份对应的 HTML 结构,dist/ 会变大一些。换来的是浏览器不需要执行任何高亮脚本。