安装 & 使用
安装
你可以使用包管理器或 使用 CDN 进行安装:
npm install -D shiki
yarn add -D shiki
pnpm add -D shiki
bun add -D shiki
集成
我们也提供了一些集成以便你使用:
使用方法
简写
使用 shiki
的最快方式是调用简写函数。它会根据你的需要加载主题和语言,并将其自动缓存到内存中。
将你的代码片段传给 codeToHtml
函数并指定 lang
和 theme
选项,它将返回一个带有语法高亮的 HTML 字符串,你可以将其嵌入到页面中。生成的 HTML 中,每个标签都有相应的内联样式,因此你不需要额外的 CSS 来进行样式设置。
import { codeToHtml } from 'shiki'
const code = 'const a = 1' // 输入代码片段
const html = await codeToHtml(code, {
lang: 'javascript',
theme: 'vitesse-dark'
})
console.log(html) // 带有高亮显示的 HTML 字符串
更进一步,你还可以使用 codeToTokens
或 codeToHast
函数来获取中间数据结构,并自行渲染它们:
import { codeToTokens } from 'shiki'
const { tokens } = await codeToTokens('<div class="foo">bar</div>', {
lang: 'html',
theme: 'min-dark'
})
import { codeToHast } from 'shiki'
const hast = await codeToHast('.text-red { color: red; }', {
lang: 'css',
theme: 'catppuccin-mocha'
})
高亮器用法
因为 Shiki 使用了 WASM,所以提供的 简写 函数是异步执行的,并在其内部按需加载主题和语言。在某些情况下,你可能需要同步地高亮代码,因此我们提供了 createHighlighter
函数来创建一个可以在后续同步使用的高亮器实例。
使用方式与 codeToHtml
函数几乎相同,其中,每个主题和语言都是动态导入的 ES 模块,最好显式地列出语言和主题以获得最佳性能。
import { createHighlighter } from 'shiki'
// `createHighlighter` 是异步的,它会初始化高亮器
// 并加载指定的语言和主题。
const highlighter = await createHighlighter({
themes: ['nord'],
langs: ['javascript'],
})
// 然后你就可以同步地使用 `highlighter.codeToHtml`
// 并使用你指定的其中一个主题和语言。
const code = highlighter.codeToHtml('const a = 1', {
lang: 'javascript',
theme: 'nord'
})
重要注意
高亮器实例应该 持续且唯一存在。你或许应该在某些地方缓存它,并在整个应用程序范围内复用。避免在热函数或者循环中调用 createHighlighter
。
如果你在 Node.js 上运行,我们建议使用 简写,它会为你管理高亮器并动态加载语言和主题。
此外,如果你要在创建高亮器后加载主题和语言,可以使用 loadTheme
和 loadLanguage
方法。
// 在创建后加载主题和语言
await highlighter.loadTheme('vitesse-light')
await highlighter.loadLanguage('css')
自 v1.0 起,shiki
要求所有的主题和语言都被显式地加载。
import { createHighlighter } from 'shiki'
const highlighter = await createHighlighter({
themes: ['slack-dark'],
langs: ['css']
})
highlighter.codeToHtml(
'const a = 1',
{ lang: 'javascript', theme: 'slack-dark' }
)
Throw error, `javascript` is not loadedawait highlighter.loadLanguage('javascript') // 载入语言
// 正常工作
如果你想一次加载所有主题和语言(并不建议),你可以遍历 bundledLanguages
和 bundledThemes
中的所有键。
import { bundledLanguages, bundledThemes, createHighlighter } from 'shiki'
const highlighter = await createHighlighter({
themes: Object.keys(bundledThemes),
langs: Object.keys(bundledLanguages),
})
highlighter.codeToHtml('const a = 1', {
lang: 'javascript',
theme: 'poimandres'
})
细粒度捆绑
导入 shiki
时,所有的主题和语言都被捆绑为异步块(async chunks)。通常情况下,如果你不使用它们,你就不必在意,因为它们不会被加载。某些情况下,如果你要控制这些捆绑包的内容,你可以使用核心(shiki/core
)来组合自己的捆绑包。
查看 细粒度捆绑 部分获取更多细节。
预设捆绑包
为了方便使用,我们还提供了一些预制的捆绑包,你可以在 捆绑包 部分了解更多的信息。
使用 CJS
为了减小包的大小,shiki
以仅 ESM 的形式发布。但由于 Node.js 支持在 CJS 中动态导入 ESM 模块,你仍可以在 CJS 中使用 Shiki。
例如以下 ESM 代码:
// ESM
import { createHighlighter } from 'shiki'
async function main() {
const highlighter = await createHighlighter({
themes: ['vitesse-dark'],
langs: ['javascript'],
})
const code = highlighter.codeToHtml('const a = 1', {
theme: 'vitesse-dark',
lang: 'javascript',
})
}
可以在 CJS 中写成:
// CJS
async function main() {
const { createHighlighter } = await import('shiki')
const highlighter = await createHighlighter({
themes: ['vitesse-dark'],
langs: ['javascript'],
})
const code = highlighter.codeToHtml('const a = 1', {
theme: 'vitesse-dark',
lang: 'javascript'
})
}
使用 CDN
要在浏览器中通过 CDN 来使用 shiki
,你可以使用 esm.run 或者 esm.sh 等服务。
<body>
<div id="foo"></div>
<script type="module">
// 指定确切的版本号
import { codeToHtml } from 'https://esm.sh/shiki@1.0.0'
// 或
// import { codeToHtml } from 'https://esm.run/shiki@1.0.0'
const foo = document.getElementById('foo')
foo.innerHTML = await codeToHtml('console.log("Hi, Shiki on CDN :)")', {
lang: 'js',
theme: 'rose-pine'
})
</script>
</body>
这非常高效,因为它只会按需加载语言和主题。对于上面的代码片段,只会发出四个请求(shiki
、shiki/themes/vitesse-light.mjs
、shiki/langs/javascript.mjs
和 shiki/wasm.mjs
),共计传输约 200KB 的数据。
Cloudflare Workers
Cloudflare Workers 不支持从二进制数据初始化 WebAssembly,因此默认的 WASM 构建将无法工作。你需要将 WASM 作为资产上传并直接导入。
同时,建议使用 细粒度捆绑 来减小捆绑的体积。
import { createHighlighterCore, loadWasm } from 'shiki/core'
import nord from 'shiki/themes/nord.mjs'
import js from 'shiki/langs/javascript.mjs'
// 将 WASM 作为资产导入
await loadWasm(import('shiki/onig.wasm'))
export default {
async fetch() {
const highlighter = await createHighlighterCore({
themes: [nord],
langs: [js],
})
return new Response(highlighter.codeToHtml('console.log(\'shiki\');', {
theme: 'nord',
lang: 'js'
}))
},
}