Skip to content

Commit 43e0fc2

Browse files
committed
perf(rehype-shiki): give the default themes by name
The default themes were passed as theme objects, which Shiki normalizes, and parses into a new vscode-textmate theme, on every highlight, and which keep it from tokenizing in a single pass. They're registered with the highlighter anyway, so they're now given by name. The output is the same. Given by name, a theme's own color replacements no longer apply to the code block's foreground and background, but the default themes' only replacement (`#616e88`) is neither. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 12d75e5 commit 43e0fc2

3 files changed

Lines changed: 19 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@node-core/rehype-shiki': minor
3+
---
4+
5+
Tokenize code once for all the themes it's highlighted in when two or more are given by name, as the default themes now are. The new `@node-core/rehype-shiki/single-pass` module exports `withSinglePassTokenization`, which does this for any Shiki highlighter.

‎packages/rehype-shiki/src/__tests__/highlighter.test.mjs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ describe('createHighlighter', async () => {
8787
highlighter.highlightToHtml('const x = 1;', 'javascript');
8888

8989
const [, options] = mockShiki.codeToHtml.mock.calls.at(-1).arguments;
90-
assert.deepStrictEqual(Object.keys(options.themes), ['light', 'dark']);
90+
assert.deepStrictEqual(options.themes, {
91+
light: 'github-light-default',
92+
dark: 'nord',
93+
});
9194
assert.strictEqual(options.defaultColor, 'light');
9295
});
9396
});

‎packages/rehype-shiki/src/highlighter.mjs‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,16 @@ const createHighlighter = ({ coreOptions = {}, highlighterOptions = {} }) => {
6464
? {}
6565
: coreOptions.themes
6666
? { theme: options.themes[0] }
67-
: { themes: DEFAULT_THEMES, defaultColor: 'light' };
67+
: {
68+
// By name, as Shiki prepares a theme object again for every
69+
// highlight, and code is only tokenized in a single pass for themes
70+
// given by name
71+
themes: {
72+
light: DEFAULT_THEMES.light.name,
73+
dark: DEFAULT_THEMES.dark.name,
74+
},
75+
defaultColor: 'light',
76+
};
6877

6978
const loadedLanguages = new Set(
7079
shiki.getLoadedLanguages().map(lang => lang.toLowerCase())

0 commit comments

Comments
 (0)