Skip to content

Commit 429c41a

Browse files
committed
Core: Switch to Shiki JavaScript Regex engine by default
1 parent 30db8dd commit 429c41a

File tree

7 files changed

+219
-67
lines changed

7 files changed

+219
-67
lines changed

.changeset/lucky-onions-eat.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'fumadocs-core': major
3+
---
4+
5+
**Switch to Shiki JavaScript Regex engine by default**
6+
7+
This is important for Cloudflare Worker compatibility, JavaScript engine is the new default over Oniguruma (WASM).
8+
9+
- `rehype-code`: replaced the `experimentalJSEngine` option with `engine: js | oniguruma`.
10+
- `fumadocs-core/highlight`: use JS engine by default, drop custom engine support, use Shiki directly instead.
11+

apps/docs/source.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ export default defineConfig({
5353
mdxOptions: {
5454
rehypeCodeOptions: {
5555
lazy: true,
56-
experimentalJSEngine: true,
5756
langs: ['ts', 'js', 'html', 'tsx', 'mdx'],
5857
inline: 'tailing-curly-colon',
5958
themes: {

packages/core/src/highlight/client.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,5 @@ export function useShiki(
2222
return `${id}:${state}`;
2323
}, [code, deps, id, options.lang]);
2424

25-
return use(
26-
(promises[key] ??= highlight(code, {
27-
...options,
28-
engine: options.engine ?? 'js',
29-
})),
30-
);
25+
return use((promises[key] ??= highlight(code, options)));
3126
}

packages/core/src/highlight/shiki.ts

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import {
2-
type Awaitable,
32
type BundledHighlighterOptions,
43
type BundledLanguage,
54
type CodeOptionsMeta,
65
type CodeOptionsThemes,
76
type CodeToHastOptionsCommon,
87
type Highlighter,
9-
type RegexEngine,
108
} from 'shiki';
119
import type { BundledTheme } from 'shiki/themes';
1210
import {
@@ -25,7 +23,12 @@ export const defaultThemes = {
2523

2624
export type HighlightOptionsCommon = CodeToHastOptionsCommon<BundledLanguage> &
2725
CodeOptionsMeta & {
28-
engine?: 'js' | 'oniguruma' | Awaitable<RegexEngine>;
26+
/**
27+
* The Regex Engine for Shiki
28+
*
29+
* @defaultValue 'js'
30+
*/
31+
engine?: 'js' | 'oniguruma';
2932
components?: Partial<Components>;
3033

3134
fallbackLanguage?: BundledLanguage;
@@ -46,7 +49,7 @@ export async function highlightHast(
4649
lang: initialLang,
4750
fallbackLanguage,
4851
components: _,
49-
engine = 'oniguruma',
52+
engine = 'js',
5053
...rest
5154
} = options;
5255
let lang = initialLang;
@@ -64,25 +67,10 @@ export async function highlightHast(
6467
themesToLoad = Object.values(themes.themes).filter((v) => v !== undefined);
6568
}
6669

67-
let highlighter;
68-
if (typeof engine === 'string') {
69-
highlighter = await getHighlighter(engine, {
70-
langs: [],
71-
themes: themesToLoad,
72-
});
73-
} else {
74-
highlighter = await getHighlighter('custom', {
75-
engine,
76-
langs: [],
77-
themes: themesToLoad,
78-
});
79-
80-
if (process.env.NODE_ENV === 'development') {
81-
console.warn(
82-
'[Fumadocs `highlight()`] Avoid passing `engine` directly. For custom engines, use `shiki` directly instead.',
83-
);
84-
}
85-
}
70+
const highlighter = await getHighlighter(engine, {
71+
langs: [],
72+
themes: themesToLoad,
73+
});
8674

8775
try {
8876
await highlighter.loadLanguage(lang as BundledLanguage);
@@ -110,14 +98,17 @@ export function hastToJsx(hast: Root, options?: Partial<ToJsxOptions>) {
11098
}
11199

112100
/**
113-
* Get Shiki highlighter instance of Fumadocs (mostly for internal use, don't recommend you to use it).
101+
* Get Shiki highlighter instance of Fumadocs (mostly for internal use, you should use Shiki directly over this).
114102
*
115-
* @param engineType - engine type, the engine specified in `options` will only be effective when this is set to `custom`.
103+
* @param engineType - Shiki Regex engine to use.
116104
* @param options - Shiki options.
117105
*/
118106
export async function getHighlighter(
119-
engineType: 'js' | 'oniguruma' | 'custom',
120-
options: BundledHighlighterOptions<BundledLanguage, BundledTheme>,
107+
engineType: 'js' | 'oniguruma',
108+
options: Omit<
109+
BundledHighlighterOptions<BundledLanguage, BundledTheme>,
110+
'engine'
111+
>,
121112
) {
122113
const { createHighlighter } = await import('shiki');
123114
let highlighter = highlighters.get(engineType);
@@ -129,12 +120,10 @@ export async function getHighlighter(
129120
engine = import('shiki/engine/javascript').then((res) =>
130121
res.createJavaScriptRegexEngine(),
131122
);
132-
} else if (engineType === 'oniguruma' || !options.engine) {
123+
} else {
133124
engine = import('shiki/engine/oniguruma').then((res) =>
134125
res.createOnigurumaEngine(import('shiki/wasm')),
135126
);
136-
} else {
137-
engine = options.engine;
138127
}
139128

140129
highlighter = createHighlighter({

packages/core/src/mdx-plugins/rehype-code.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const rehypeCodeDefaultOptions: RehypeCodeOptions = {
2424
themes: defaultThemes,
2525
defaultColor: false,
2626
defaultLanguage: 'plaintext',
27-
experimentalJSEngine: false,
27+
engine: 'js',
2828
transformers: [
2929
transformerNotationHighlight({
3030
matchAlgorithm: 'v3',
@@ -61,6 +61,13 @@ function parseLineNumber(str: string, data: Record<string, unknown>) {
6161
}
6262

6363
export type RehypeCodeOptions = RehypeShikiOptions & {
64+
/**
65+
* The regex engine to use.
66+
*
67+
* @defaultValue 'js'
68+
*/
69+
engine?: 'js' | 'oniguruma';
70+
6471
/**
6572
* Filter meta string before processing
6673
*/
@@ -77,13 +84,6 @@ export type RehypeCodeOptions = RehypeShikiOptions & {
7784
* @defaultValue true
7885
*/
7986
tab?: boolean;
80-
81-
/**
82-
* Enable Shiki's experimental JS engine
83-
*
84-
* @defaultValue false
85-
*/
86-
experimentalJSEngine?: boolean;
8787
};
8888

8989
/**
@@ -124,19 +124,16 @@ export function rehypeCode(
124124
transformers.push(transformerTab());
125125
}
126126

127-
const highlighter = getHighlighter(
128-
options.experimentalJSEngine ? 'js' : 'oniguruma',
129-
{
130-
themes:
131-
'themes' in options
132-
? (Object.values(options.themes).filter(Boolean) as BuiltinTheme[])
133-
: [options.theme],
134-
langs:
135-
options.langs ??
136-
(options.lazy ? ['ts', 'tsx'] : Object.keys(bundledLanguages)),
137-
langAlias: options.langAlias,
138-
},
139-
);
127+
const highlighter = getHighlighter(options.engine ?? 'js', {
128+
themes:
129+
'themes' in options
130+
? (Object.values(options.themes).filter(Boolean) as BuiltinTheme[])
131+
: [options.theme],
132+
langs:
133+
options.langs ??
134+
(options.lazy ? ['ts', 'tsx'] : Object.keys(bundledLanguages)),
135+
langAlias: options.langAlias,
136+
});
140137

141138
const transformer = highlighter.then((loaded) =>
142139
rehypeShikiFromHighlighter(loaded, {

packages/mdx-remote/test/index.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const files = await glob('./fixtures/*.mdx', {
1414
const compiler = createCompiler({
1515
development: true,
1616
rehypeCodeOptions: {
17-
experimentalJSEngine: true,
1817
lazy: true,
1918
themes: {
2019
light: 'github-light',
@@ -26,7 +25,6 @@ const compiler = createCompiler({
2625
const compilerProduction = createCompiler({
2726
development: false,
2827
rehypeCodeOptions: {
29-
experimentalJSEngine: true,
3028
lazy: true,
3129
themes: {
3230
light: 'github-light',

0 commit comments

Comments
 (0)