深浅色模式
Shiki 支持输出浅色和深色两个主题。与 markdown-it-shiki 将代码渲染两次的实现不同,Shiki 的多主题实现使用 CSS 变量来存储每个标签上的颜色;其在性能上更高效,并且包更小。
将 codeToHtml
上的 theme
选项改为含 light
和 dark
两键的 options
来指定两个主题。
ts
import { codeToHtml } from 'shiki'
const code = await codeToHtml('console.log("hello")', {
lang: 'javascript',
themes: {
light: 'min-light',
dark: 'nord',
}
})
这会生成以下 HTML(示例预览):
html
<pre
class="shiki shiki-themes min-light nord"
style="background-color:#ffffff;--shiki-dark-bg:#2e3440ff;color:#24292eff;--shiki-dark:#d8dee9ff"
tabindex="0"
>
<code>
<span class="line">
<span style="color:#1976D2;--shiki-dark:#D8DEE9">console</span>
<span style="color:#6F42C1;--shiki-dark:#ECEFF4">.</span>
<span style="color:#6F42C1;--shiki-dark:#88C0D0">log</span>
<span style="color:#24292EFF;--shiki-dark:#D8DEE9FF">(</span>
<span style="color:#22863A;--shiki-dark:#ECEFF4">"</span>
<span style="color:#22863A;--shiki-dark:#A3BE8C">hello</span>
<span style="color:#22863A;--shiki-dark:#ECEFF4">"</span>
<span style="color:#24292EFF;--shiki-dark:#D8DEE9FF">)</span>
</span>
</code>
</pre>
为了使它们响应你的网站颜色模式,需要加入一些额外的 CSS 片段:
基于媒体查询的深色模式
css
@media (prefers-color-scheme: dark) {
.shiki,
.shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
/* 可选,用于定义字体样式 */
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
}
基于类名的深色模式
css
html.dark .shiki,
html.dark .shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
/* 可选,用于定义字体样式 */
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
多主题
还支持超过两个主题。在 theme
对象中,你可以创建任意数量的主题,并使用 defaultColor
选项指定默认主题。
ts
import { codeToHtml } from 'shiki'
const code = await codeToHtml('console.log("hello")', {
lang: 'javascript',
themes: {
light: 'github-light',
dark: 'github-dark',
dim: 'github-dimmed',
// 任意数量的主题
},
// 可选的自定义选项
defaultColor: 'light',
cssVariablePrefix: '--shiki-'
})
标签会以类似如下形式生成:
html
<span style="color:#1976D2;--shiki-dark:#D8DEE9;--shiki-dim:#566575">console</span>
然后,修改你的 CSS 代码以控制每个主题何时生效,这是一个示例:
不使用默认颜色
如果你想完全控制颜色或避免使用 !important
进行覆盖,你可以将 defaultColor
设置为 false
来禁用默认颜色。
ts
import { codeToHtml } from 'shiki'
const code = await codeToHtml('console.log("hello")', {
lang: 'javascript',
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
defaultColor: false, // <--
})
此时,标签会以类似如下形式生成:
html
<span style="--shiki-dark:#D8DEE9;--shiki-light:#2E3440">console</span>
在这种情况下,生成的 HTML 将没有默认样式,你需要添加自己的 CSS 来控制它们的颜色。