跳至內容
Fumadocs

語法突顯器

使用 Shiki 或您選擇的語法突顯器,為程式碼進行語法突顯。

Fumadocs 預設使用 Shiki 為程式碼進行語法突顯。您也可以自行建立語法突顯器,並傳入需要語法突顯程式碼的地方;如此一來,便不會載入 Shiki。

lib/highlighter.ts
// npm i @pierre/highlights
import { createHighlights } from 'fumadocs-core/highlight/highlights';
import githubLight from '@pierre/highlights/themes/github-light';
import githubDark from '@pierre/highlights/themes/github-dark';

export const highlighter = createHighlights({
  themes: { light: githubLight, dark: githubDark },
});

Highlights 以 WebAssembly 撰寫,速度比 Shiki 快上許多倍。它內建 80 種語言 (其他語言會以純文字呈現) ,使用來自 @pierre/highlights/themes 的專屬主題,並透過相容層 shikiTransformers 執行 Shiki transformer。

highlighter.override() 可使用不同的選項 (例如其他 transformer) 建立新的語法突顯器。

使用方式

rehypeCodeFromHighlighter 是一個 rehype 外掛。請用它取代 Fumadocs MDX 預設的 Shiki 外掛:

source.config.ts
import { defineConfig } from 'fumadocs-mdx/config';
import { rehypeCodeFromHighlighter } from 'fumadocs-core/mdx-plugins/rehype-code.core';
import { highlighter } from './lib/highlighter';

export default defineConfig({
  mdxOptions: {
    // 停用預設的 Shiki 外掛
    rehypeCodeOptions: false,
    rehypePlugins: (v) => [
      () =>
        rehypeCodeFromHighlighter(
          // 搭配 Fumadocs 的 transformer(例如標記法與圖示)建立
          ({ transformers }) => highlighter.override({ shikiTransformers: transformers }),
        ),
      ...v,
    ],
  },
});

將它傳給程式碼區塊元件:

components/codeblock.tsx
import { createServerCodeBlock } from 'fumadocs-ui/components/codeblock.rsc';
import { highlighter } from '@/lib/highlighter';

export const ServerCodeBlock = createServerCodeBlock({ highlighter });

各整合會在其主要進入點接收它:

整合選項
本機 Markdown (Sätteri) 在 hastPlugins 中使用 @fumadocs/satteri/rehype-code 的 rehypeCodeFromHighlighter()
Python、Local HTMLcreatePython({ highlighter })、localHtml({ highlighter })
OpenAPI、GraphQL、AsyncAPIcreateOpenAPIPage({ highlighter })
型別表格remarkAutoTypeTable({ highlighter })、<AutoTypeTable highlighter />
shadcn@fumadocs/shadcn/rsc 的 createSnippet({ highlighter })

若 Fumadocs 會為程式碼區塊加入 transformer (例如 rehypeCodeFromHighlighter(),以及 Python、Local HTML 與 shadcn 的整合) ,則會改由一個函式接收這些 transformer。

Shiki Factory

Fumadocs 透過 Shiki factory 管理 Shiki 實例,您也可以為特定用途自行建立一個,例如使用細粒度的 bundle:

import { createShikiFactory } from 'fumadocs-core/highlight/shiki';

export const myShikiFactory = createShikiFactory({
  async init(options) {
    const { createHighlighter, createJavaScriptRegexEngine } = await import('shiki');

    return createHighlighter({
      langs: [],
      themes: [],
      langAlias: options?.langAlias,
      engine: createJavaScriptRegexEngine(),
    });
  },
});

接著將它傳給不同的模組/功能:

'use client';
import * as Base from 'fumadocs-ui/components/dynamic-codeblock.core';

export type DynamicCodeblockProps = Omit<Base.DynamicCodeblockProps, 'highlighter'>;

export function DynamicCodeBlock(props: DynamicCodeblockProps) {
  return <Base.DynamicCodeBlock highlighter={() => myShikiFactory.getOrInit()} {...props} />;
}

自訂語法突顯器

請實作 Highlighter 介面:

import type { Highlighter } from 'fumadocs-core/highlight';

export const highlighter: Highlighter = {
  codeToHast(code, { lang, structure, meta }) {
    // 回傳 `pre > code > span.line`,並將 `meta` 放在 `<pre>` 上;若 `structure` 為 `inline`,則回傳 `<code>` 的內容
  },
  // 選用,用於隨需載入的語言
  async loadLanguage(...langs) {},
};

Fumadocs UI 會透過 --shiki-light 與 --shiki-dark 等 CSS 變數為 token 上色。您可以像傳入其他語法突顯器一樣傳入它,或使用 rehypeCodeFromHighlighter,在您自己的 rehype 管線中進行語法突顯:

import { rehypeCodeFromHighlighter } from 'fumadocs-core/mdx-plugins/rehype-code.core';

unified().use(rehypeCodeFromHighlighter, highlighter);

How is this guide?

最後更新於