mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Core: use internal store for Shiki highlighter instances
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-core': patch
|
||||
---
|
||||
|
||||
use internal store for Shiki highlighter instances
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
type CodeToHastOptionsCommon,
|
||||
type RegexEngine,
|
||||
type Awaitable,
|
||||
type Highlighter,
|
||||
type BundledHighlighterOptions,
|
||||
} from 'shiki';
|
||||
import type { BundledTheme } from 'shiki/themes';
|
||||
import { type Components, toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
||||
@@ -40,9 +42,9 @@ export type HighlightOptions = CodeToHastOptionsCommon<BundledLanguage> &
|
||||
components?: Partial<Components>;
|
||||
};
|
||||
|
||||
let defaultEngine: RegexEngine | undefined;
|
||||
const highlighters = new Map<string, Promise<Highlighter>>();
|
||||
|
||||
export async function _highlight(code: string, options: HighlightOptions) {
|
||||
const { getSingletonHighlighter } = await import('shiki');
|
||||
const { lang, components: _, engine, ...rest } = options;
|
||||
|
||||
let themes: CodeOptionsThemes<BundledTheme> = { themes: defaultThemes };
|
||||
@@ -52,13 +54,9 @@ export async function _highlight(code: string, options: HighlightOptions) {
|
||||
themes = { themes: options.themes };
|
||||
}
|
||||
|
||||
const highlighter = await getSingletonHighlighter({
|
||||
const highlighter = await getHighlighter('custom', {
|
||||
engine,
|
||||
langs: [lang],
|
||||
engine:
|
||||
engine ??
|
||||
(defaultEngine ??= await import('shiki/engine/oniguruma').then((res) =>
|
||||
res.createOnigurumaEngine(import('shiki/wasm')),
|
||||
)),
|
||||
themes:
|
||||
'theme' in themes
|
||||
? [themes.theme]
|
||||
@@ -84,6 +82,47 @@ export function _renderHighlight(hast: Root, options?: HighlightOptions) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function getHighlighter(
|
||||
engineType: 'js' | 'oniguruma' | 'custom',
|
||||
options: BundledHighlighterOptions<BundledLanguage, BundledTheme>,
|
||||
) {
|
||||
const { createHighlighter } = await import('shiki');
|
||||
let highlighter = highlighters.get(engineType);
|
||||
|
||||
if (!highlighter) {
|
||||
let engine = options.engine;
|
||||
|
||||
if (engineType === 'js') {
|
||||
const { createJavaScriptRegexEngine } = await import(
|
||||
'shiki/engine/javascript'
|
||||
);
|
||||
engine = createJavaScriptRegexEngine();
|
||||
}
|
||||
|
||||
if (engineType === 'oniguruma' || !engine) {
|
||||
const { createOnigurumaEngine } = await import('shiki/engine/oniguruma');
|
||||
engine = createOnigurumaEngine(import('shiki/wasm'));
|
||||
}
|
||||
|
||||
highlighter = createHighlighter({
|
||||
...options,
|
||||
engine,
|
||||
});
|
||||
}
|
||||
|
||||
highlighters.set(engineType, highlighter);
|
||||
return highlighter.then(async (instance) => {
|
||||
await Promise.all([
|
||||
// @ts-expect-error unknown
|
||||
instance.loadLanguage(options.langs),
|
||||
// @ts-expect-error unknown
|
||||
instance.loadTheme(options.themes),
|
||||
]);
|
||||
|
||||
return instance;
|
||||
});
|
||||
}
|
||||
|
||||
export async function highlight(
|
||||
code: string,
|
||||
options: HighlightOptions,
|
||||
|
||||
@@ -8,17 +8,18 @@ import {
|
||||
} from '@shikijs/transformers';
|
||||
import type { Processor, Transformer } from 'unified';
|
||||
import {
|
||||
getSingletonHighlighter,
|
||||
type ShikiTransformer,
|
||||
type BuiltinTheme,
|
||||
bundledLanguages,
|
||||
} from 'shiki';
|
||||
import type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
||||
import { createOnigurumaEngine } from 'shiki/engine/oniguruma';
|
||||
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript';
|
||||
import type { IconOptions, CodeBlockIcon } from './transformer-icon';
|
||||
import { transformerIcon } from './transformer-icon';
|
||||
import { createStyleTransformer, defaultThemes } from '@/highlight/shiki';
|
||||
import {
|
||||
createStyleTransformer,
|
||||
defaultThemes,
|
||||
getHighlighter,
|
||||
} from '@/highlight/shiki';
|
||||
|
||||
interface MetaValue {
|
||||
name: string;
|
||||
@@ -145,21 +146,20 @@ export function rehypeCode(
|
||||
transformers.push(transformerTab());
|
||||
}
|
||||
|
||||
const highlighter = getSingletonHighlighter({
|
||||
engine: options.experimentalJSEngine
|
||||
? createJavaScriptRegexEngine()
|
||||
: createOnigurumaEngine(() => import('shiki/wasm')),
|
||||
themes:
|
||||
'themes' in options
|
||||
? (Object.values(options.themes).filter(Boolean) as BuiltinTheme[])
|
||||
: [options.theme],
|
||||
langs:
|
||||
options.langs ??
|
||||
(options.lazy ? undefined : Object.keys(bundledLanguages)),
|
||||
});
|
||||
const highlighter = getHighlighter(
|
||||
options.experimentalJSEngine ? 'js' : 'oniguruma',
|
||||
{
|
||||
themes:
|
||||
'themes' in options
|
||||
? (Object.values(options.themes).filter(Boolean) as BuiltinTheme[])
|
||||
: [options.theme],
|
||||
langs:
|
||||
options.langs ?? (options.lazy ? [] : Object.keys(bundledLanguages)),
|
||||
},
|
||||
);
|
||||
|
||||
const transformer = highlighter.then((instance) =>
|
||||
rehypeShikiFromHighlighter(instance, {
|
||||
const transformer = highlighter.then((loaded) =>
|
||||
rehypeShikiFromHighlighter(loaded, {
|
||||
...options,
|
||||
transformers,
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user