Skip to content

安装和使用

NPM versionNPM downloadsGitHub

安装

你可以使用包管理器或使用 CDN 进行安装:

sh
npm install -D shiki
sh
yarn add -D shiki
sh
pnpm add -D shiki
sh
bun add -D shiki

集成

我们也提供了一些集成以便你使用:

使用方法

简写

使用 shiki 的最快方式是调用简写函数。它会根据你的需要加载主题和语言,并将其自动缓存到内存中。

将你的代码片段传给 codeToHtml 函数并指定 langtheme 选项,它将返回一个带有语法高亮的 HTML 字符串,你可以将其嵌入到页面中。生成的 HTML 中,每个标签都有相应的内联样式,因此你不需要额外的 CSS 来进行样式设置。

ts
import {  } from 'shiki'

const  = 'const a = 1' // 输入代码片段
const  = await (, {
  : 'javascript',
  : 'vitesse-dark'
})

.() // 带有高亮显示的 HTML 字符串

更进一步,你还可以使用 codeToTokenscodeToHast 函数来获取中间数据结构,并自行渲染它们:

ts
import {  } from 'shiki'

const {  } = await ('<div class="foo">bar</div>', {
  : 'html',
  : 'min-dark'
})
ts
import {  } from 'shiki'

const  = await ('.text-red { color: red; }', {
  : 'css',
  : 'catppuccin-mocha'
})

高亮器用法

因为 Shiki 使用了 WASM,所以提供的简写函数是异步执行的,并在其内部按需加载主题和语言。在某些情况下,你可能需要同步地高亮代码,因此我们提供了 createHighlighter 函数来创建一个可以在后续同步使用的高亮器实例。

使用方式与 codeToHtml 函数几乎相同,其中,每个主题和语言都是动态导入的 ES 模块,最好显式地列出语言和主题以获得最佳性能。

ts
import {  } from 'shiki'

// `createHighlighter` 是异步的,它会初始化高亮器
// 并加载指定的语言和主题。
const  = await ({
  : ['nord'],
  : ['javascript'],
})

// 然后你就可以同步地使用 `highlighter.codeToHtml`
// 并使用你指定的其中一个主题和语言。
const  = .('const a = 1', {
  : 'javascript',
  : 'nord'
})

重要注意

高亮器实例应该 持续且唯一存在。你或许应该在某些地方缓存它,并在整个应用程序范围内复用。避免在热函数或者循环中调用 createHighlighter

如果你在 Node.js 上运行,我们建议使用 简写,它会为你管理高亮器并动态加载语言和主题。

此外,如果你要在创建高亮器后加载主题和语言,可以使用 loadThemeloadLanguage 方法。

ts
// 在创建后加载主题和语言
await .('vitesse-light')
await .('css')

自 v1.0 起,shiki 要求所有的主题和语言都被显式地加载。

ts
import {  } from 'shiki'

const  = await ({
  : ['slack-dark'],
  : ['css']
})

.(
  'const a = 1',
  { : 'javascript', : 'slack-dark' }
)
Throw error, `javascript` is not loaded
await .('javascript') // 载入语言 // 正常工作

如果你想一次加载所有主题和语言 (并不建议),你可以遍历 bundledLanguagesbundledThemes 中的所有键。

ts
import { , ,  } from 'shiki'

const  = await ({
  : .(),
  : .(),
})

.('const a = 1', {
  : 'javascript',
  : 'poimandres'
})

细粒度捆绑

导入 shiki 时,所有的主题和语言都被捆绑为异步块 (async chunks)。通常情况下,如果你不使用它们,你就不必在意,因为它们不会被加载。某些情况下,如果你要控制这些捆绑包的内容,你可以使用核心 (shiki/core) 来组合自己的捆绑包。

查看细粒度捆绑包部分了解更多详细信息。

预设捆绑包

为了方便使用,我们还提供了一些预制的捆绑包,你可以在捆绑包部分了解更多的信息。

使用 CJS

为了减小包的大小,shiki 以仅 ESM 的形式发布。但由于 Node.js 支持在 CJS 中动态导入 ESM 模块,你仍可以在 CJS 中使用 Shiki。

例如以下 ESM 代码:

ts
// ESM
import {  } from 'shiki'

async function () {
  const  = await ({
    : ['vitesse-dark'],
    : ['javascript'],
  })

  const  = .('const a = 1', {
    : 'vitesse-dark',
    : 'javascript',
  })
}

可以在 CJS 中写成:

ts
// CJS
async function () {
  const {  } = await import('shiki')

  const  = await ({
    : ['vitesse-dark'],
    : ['javascript'],
  })

  const  = .('const a = 1', {
    : 'vitesse-dark',
    : 'javascript'
  })
}

使用 CDN

要在浏览器中通过 CDN 来使用 shiki,你可以使用 esm.run 或者 esm.sh 等服务。

html
<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>

这非常高效,因为它只会按需加载语言和主题。对于上面的代码片段,只会发出四个请求 (shikishiki/themes/vitesse-light.mjsshiki/langs/javascript.mjsshiki/wasm.mjs),共计传输约 200KB 的数据。

查看示例

Cloudflare Workers

Cloudflare Workers 不支持从二进制数据初始化 WebAssembly,因此默认的 WASM 构建将无法工作。你需要将 WASM 作为资产上传并直接导入。

同时,建议使用细粒度捆绑来减小捆绑的体积。

ts
import { ,  } from 'shiki/core'
import  from 'shiki/langs/javascript.mjs'
import  from 'shiki/themes/nord.mjs'

// 将 WASM 作为资产导入
await (import('shiki/onig.wasm'))

export default {
  async () {
    const  = await ({
      : [],
      : [],
    })

    return new (.('console.log(\'shiki\');', {
      : 'nord',
      : 'js'
    }))
  },
}