next.js + daisyui + shiki 代码块多主题支持一例

文中给出的例子同时也是本站使用的方案(有改动,截至文章发布时间,以后说不定会重构,哈哈)。

另,shiki 版本为 3.x。

使用 shiki 生成代码块

创建 highlighter:

TYPESCRIPT
const highlighter = await createHighlighter({
  // 这里列会用到的主题
  // 注意,不是说 themes 要以 [light, dark] 的格式填主题
  // 你完全可以多列几个
  themes: ["github-light", "github-dark"],
  // 这里列你有用到的语言
  langs: ["typescript"],
});

生成代码块:

TYPESCRIPT
const rsl = highlighter.codeToHast(code, {
  lang,
  // 这里才是控制 light 和 dark 要用什么主题的
  themes: {
    light: "github-light",
    dark: "github-dark",
  },
});

编写 css

直接用的问题是:shiki 不会自己生成 css 文件,所以,要手动写切换主题的 css。正好 daisyui 也有主题切换这一概念:

HTML
<html data-theme="light"></html>

我们就利用一下这个:

CSS
@media (prefers-color-scheme: dark) {
  html:not([data-theme]) .shiki,
  html:not([data-theme]) .shiki span {
    color: var(--shiki-dark) !important;
  }
}

html[data-theme="dark"] .shiki,
html[data-theme="dark"] .shiki span {
  color: var(--shiki-dark) !important;
}

另外,shiki 会注入背景色到 <pre> 的 style 里,所以要写 js 代码把 style 里的 background-color 干掉。

Next.js