Skip to content

Commit 61e78d9

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 whose tokens can't be cached for both. They're registered with the highlighter anyway, so they're now given by name, in a `DEFAULT_THEME_OPTIONS` constant. 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 a07ab77 commit 61e78d9

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+
Cache each line's tokens for all the themes code is highlighted in when two or more are given by name, as the default themes now are, instead of tokenizing it again for each. The new `@node-core/rehype-shiki/tokenization-cache` module exports `withTokenizationCache`, 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
@@ -20,6 +20,15 @@ const DEFAULT_THEMES = {
2020
dark: DEFAULT_DARK_THEME,
2121
};
2222

23+
// The default themes by name: Shiki prepares a theme object again for every
24+
// highlight, and only caches tokens for all the themes given by name
25+
const DEFAULT_THEME_OPTIONS = {
26+
themes: Object.fromEntries(
27+
Object.entries(DEFAULT_THEMES).map(([color, { name }]) => [color, name])
28+
),
29+
defaultColor: 'light',
30+
};
31+
2332
const FALLBACK_LANGUAGE = 'text';
2433

2534
/**
@@ -64,7 +73,7 @@ const createHighlighter = ({ coreOptions = {}, highlighterOptions = {} }) => {
6473
? {}
6574
: coreOptions.themes
6675
? { theme: options.themes[0] }
67-
: { themes: DEFAULT_THEMES, defaultColor: 'light' };
76+
: DEFAULT_THEME_OPTIONS;
6877

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

0 commit comments

Comments
 (0)