@shikijs/rehype
rehype 的 Shiki 插件。
安装
sh
npm i -D @shikijs/rehypesh
yarn add -D @shikijs/rehypesh
pnpm add -D @shikijs/rehypesh
bun add -D @shikijs/rehypesh
deno add npm:@shikijs/rehype使用方法
ts
import rehypeShiki from '@shikijs/rehype'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import { unified } from 'unified'
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShiki, {
// 或者使用单个主题的 `theme`
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark',
}
})
.use(rehypeStringify)
.process(await fs.readFile('./input.md'))@shikijs/rehype 的默认导出使用来自 getSingletonHighlighter 的共享 shiki 实例,该实例将在进程间保持。如果你希望完全控制高亮器的生命周期,请改用 精细粒度打包 @shikijs/rehype/core。
精细粒度打包
默认情况下,会导入 shiki 的完整包。如果你使用的是精细粒度打包,你可以从 @shikijs/rehype/core 导入 rehypeShikiFromHighlighter,并传入你自己的高亮器:
ts
import rehypeShikiFromHighlighter from '@shikijs/rehype/core'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import { createHighlighterCore } from 'shiki/core'
import { createOnigurumaEngine } from 'shiki/engine/oniguruma'
import { unified } from 'unified'
const highlighter = await createHighlighterCore({
themes: [
import('@shikijs/themes/vitesse-light')
],
langs: [
import('@shikijs/langs/javascript'),
],
engine: createOnigurumaEngine(() => import('shiki/wasm'))
})
const raw = await fs.readFile('./input.md')
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShikiFromHighlighter, highlighter, {
// 或者使用单个主题的 `theme`
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark',
}
})
.use(rehypeStringify)
.processSync(raw) // 也可以同步处理特性
行内代码
你也可以通过 inline 选项高亮行内代码。
| 选项 | 示例 | 说明 |
|---|---|---|
false | - | 禁用行内代码高亮(默认) |
'tailing-curly-colon' | let a = 1{:js} | 使用 {:language} 标记在代码块内进行高亮 |
在 Rehype 插件中启用 inline:
ts
import rehypeShiki from '@shikijs/rehype'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import { unified } from 'unified'
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShiki, {
inline: 'tailing-curly-colon', // 或其他选项
// ...
})
.use(rehypeStringify)
.process(await fs.readFile('./input.md'))然后你可以在 markdown 中使用行内代码:
md
This code `console.log("Hello World"){:js}` will be highlighted.后处理转换器
INFO
postprocess 转换器钩子仅在生成 HTML 字符串(即使用 codeToHtml)时调用。由于 @shikijs/rehype 是基于 HAST(超文本抽象语法树)而非 HTML 字符串进行操作,所以不会执行 postprocess 转换器。
这是有意为之:在 rehype 中运行 postprocess 钩子需要进行 HAST → HTML → 运行 postprocess → 解析回 HAST 的转换流程,这样会改变语义,可能让期望仅操作 HAST 的用户感到意外。
针对基于 HTML 的后处理的解决方案
如果你需要在 rehype 中执行基于 HTML 的后处理,可以使用一个 root 转换器,它:
- 使用
hast-util-to-html将 HAST 片段转换成 HTML - 运行你的 HTML 转换
- 使用
hast-util-from-html转换回 HAST
示例:
ts
import { fromHtml } from 'hast-util-from-html'
import { toHtml } from 'hast-util-to-html'
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShiki, {
themes: {
light: 'vitesse-light',
dark: 'vitesse-dark',
},
transformers: [
{
name: 'custom-html-postprocessor',
root(node) {
// 转换 HAST 到 HTML
const html = toHtml(node)
// 执行自定义 HTML 转换
const processedHtml = myCustomPostprocess(html)
// 解析回 HAST
const newNode = fromHtml(processedHtml, { fragment: true })
// 替换节点
return newNode
}
}
]
})
.use(rehypeStringify)
.process(await fs.readFile('./input.md'))