Choose Theme

Shortcuts: ⌘ ⇧ P
↑↓ Navigate • Enter Confirm • Esc Close
🖥️ System
🌻 Latte
🦭 Nord
🐻‍❄️ Nord Night
🌺 Macchiato
🌿 Mocha
🏙 Tokyo Night

Use Shiki StyleToClass Transformer

Shiki作为比较流行的代码高亮工具,提供比highlight.js更准确的代码高亮效果;以console.log("hello")为例,Shiki高亮器按照代码语义将其拆分为6部分;其被<span>标签包裹,标签的内联样式中可能有color,font-style等属性以及一些CSS变量[1],用于实现颜色[2]以及字体[3]多主题适配

JS
const code = await codeToHtml('console.log("hello")', {  lang: 'javascript',  themes: { light: 'min-light', dark: 'nord', }})

上面的示例输出中,HTML体积尚可接受,一是代码量很小,此外是仅应用了 min-lightnord 两种主题,且这两个主题仅在实例代码中嵌入了 color 属性以及 --shiki-dark 变量;

当这些条件不满足时,输出的HTML体积会大幅增加。例如个人博客中包含一些长代码片段,同时应用了 catppuccin-latte, catppuccin-mocha, tokyo-night, nord, tokyo-night 5种主题,输出的HTML就略显臃肿;下文将记录如何使用 styleToClass Transformer 来优化Shiki高亮器的输出。

Solutions

操作很简单,引入 @shikijs/transformers 包中的 styleToClass Transformer,并在调用 codeToHtml 时传入该Transformer即可

TS
import { writeFileSync } from "fs";import { transformerStyleToClass } from '@shikijs/transformers'import { codeToHtml } from 'shiki'const toClass = transformerStyleToClass({  classPrefix: '__shiki_',})const code = `console.log('hello')`const html = await codeToHtml(code, {  lang: 'ts',  themes: { dark: 'vitesse-dark', light: 'vitesse-light', },  transformers: [toClass],})const css = toClass.getCSS()// 将生成的CSS写入~/Downloads/shiki_style_to_class.css文件writeFileSync(join(process.env.HOME || process.env.USERPROFILE || ".", "Downloads/shiki_style_to_class.css"), cssContent, "utf-8");

要注意的一点是,当与@shikijs/colorized-brackets一起使用时,styleToClass Transformer 应该放在该 colorizedBrackets 之后;否则colorizedBrackets 的样式依然会被内联到HTML中,而不是转换为类名。同理,其他会生成内联样式的Transformer也应放在styleToClass之前。

transformerStyleToClass

工作原理摘抄自官方文档,内容如下
Convert Shiki’s inline styles to unique classes.

Class names are generated based on the hash value of the style object with the prefix/suffix you provide. You can put this transformer in multiple highlights passes and then get the CSS at the end to reuse the exact same styles. As Shiki doesn’t handle CSS, it’s on your integration to decide how to extract and apply/bundle the CSS.

CSS内容写入文件后,在Blog或网站中引入该CSS文件即可;对于Hexo博客,可使用Efterklang/hexo-shiki-highlight插件

效果

以如下CSS Codeblock为例,测试启用/禁用 styleToClass Transformer前后,生成<code>体积对比,启用的主题为前面提到的5种主题

MD
```csscode span {  font-style: var(--shiki-light-font-style);}:where([data-theme="tokyo_night"]) {  code span {    font-style: var(--shiki-tokyo-font-style);    color: var(--shiki-tokyo);  }}:where([data-theme="mocha"], [data-theme="macchiato"]) {  code span {    font-style: var(--shiki-dark-font-style);    color: var(--shiki-dark);  }}```
TransformerHTML体积
启用 styleToClass5.2KB
禁用 styleToClass11.0KB

测试了几组代码,基本可以压缩45%+的体积。使用External CSS代替Inline CSS的主要优势还是在可复用性,可维护性和可读性上,此外就是Inline CSS不支持hover等伪类样式,而External CSS则可以轻松实现。

对于体积压缩而言,除非代码量很大/应用了多种主题,否则体积压缩效果可能不明显👉 👈


  1. Custom properties (sometimes referred to as CSS variables or cascading variables) are entities defined by CSS authors that represent specific values to be reused throughout a document. They are set using the color at-rule or by custom property syntax (e.g., background-color). Custom properties are accessed using the CSS --shiki-{theme-name} function (e.g., --shiki-{theme-name}-bg). Using CSS custom properties (variables) - CSS | MDN ↩︎

  2. Shiki高亮器生成的代码片段中,包含默认主题的颜色样式,例如 {theme-name}codeToHtml,对于非默认主题,这些样式通过themes, font-style等CSS变量进行存储,其中font-weighttext-decoration--shiki-{theme-name}-font-style中的键名 深浅色模式 | Shiki 中文文档 ↩︎

  3. Shiki高亮器生成的代码片段中,包含默认主题的字体样式,例如 --shiki-{theme-name}-font-weight, --shiki-{theme-name}-text-decoration, {theme-name},对于非默认主题,这些样式通过codeToHtml, themes, @property等CSS变量进行存储,其中--primary-color: blue;var()color: var(--primary-color);中的键名深浅色模式 | Shiki 中文文档 ↩︎

Use Shiki StyleToClass Transformer

https://vluv.space/shiki_style_to_class/

作者

GnixAij

发布于

2025-11-30

更新于

2025-11-30

许可协议

评论