@shikijs/core 3.22.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,2446 +1,1417 @@
1
- import { ShikiError as ShikiError$1 } from '@shikijs/types';
2
- export * from '@shikijs/types';
3
- import { FontStyle, INITIAL, EncodedTokenMetadata, Registry as Registry$1, Theme } from '@shikijs/vscode-textmate';
4
- import { toHtml } from 'hast-util-to-html';
1
+ import { ShikiError as ShikiError$1 } from "@shikijs/types";
2
+ import { ShikiError, applyColorReplacements, codeToTokensBase as codeToTokensBase$1, codeToTokensWithThemes, codeToTokensWithThemes as codeToTokensWithThemes$1, createShikiInternal, createShikiInternalSync, createShikiPrimitive, createShikiPrimitive as createShikiPrimitive$1, createShikiPrimitiveAsync, createShikiPrimitiveAsync as createShikiPrimitiveAsync$1, getLastGrammarState, getLastGrammarStateFromMap, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, normalizeGetter, normalizeTheme, resolveColorReplacements, setLastGrammarStateToMap, splitLines, splitLines as splitLines$1, toArray, tokenizeWithTheme } from "@shikijs/primitive";
3
+ import { FontStyle } from "@shikijs/vscode-textmate";
4
+ import { toHtml } from "hast-util-to-html";
5
5
 
6
- function resolveColorReplacements(theme, options) {
7
- const replacements = typeof theme === "string" ? {} : { ...theme.colorReplacements };
8
- const themeName = typeof theme === "string" ? theme : theme.name;
9
- for (const [key, value] of Object.entries(options?.colorReplacements || {})) {
10
- if (typeof value === "string")
11
- replacements[key] = value;
12
- else if (key === themeName)
13
- Object.assign(replacements, value);
14
- }
15
- return replacements;
16
- }
17
- function applyColorReplacements(color, replacements) {
18
- if (!color)
19
- return color;
20
- return replacements?.[color?.toLowerCase()] || color;
21
- }
22
-
23
- function toArray(x) {
24
- return Array.isArray(x) ? x : [x];
25
- }
26
- async function normalizeGetter(p) {
27
- return Promise.resolve(typeof p === "function" ? p() : p).then((r) => r.default || r);
28
- }
29
- function isPlainLang(lang) {
30
- return !lang || ["plaintext", "txt", "text", "plain"].includes(lang);
31
- }
32
- function isSpecialLang(lang) {
33
- return lang === "ansi" || isPlainLang(lang);
34
- }
35
- function isNoneTheme(theme) {
36
- return theme === "none";
37
- }
38
- function isSpecialTheme(theme) {
39
- return isNoneTheme(theme);
40
- }
6
+ export * from "@shikijs/types"
41
7
 
8
+ //#region src/utils/hast.ts
9
+ /**
10
+ * Utility to append class to a hast node
11
+ *
12
+ * If the `property.class` is a string, it will be splitted by space and converted to an array.
13
+ */
42
14
  function addClassToHast(node, className) {
43
- if (!className)
44
- return node;
45
- node.properties ||= {};
46
- node.properties.class ||= [];
47
- if (typeof node.properties.class === "string")
48
- node.properties.class = node.properties.class.split(/\s+/g);
49
- if (!Array.isArray(node.properties.class))
50
- node.properties.class = [];
51
- const targets = Array.isArray(className) ? className : className.split(/\s+/g);
52
- for (const c of targets) {
53
- if (c && !node.properties.class.includes(c))
54
- node.properties.class.push(c);
55
- }
56
- return node;
15
+ if (!className) return node;
16
+ node.properties ||= {};
17
+ node.properties.class ||= [];
18
+ if (typeof node.properties.class === "string") node.properties.class = node.properties.class.split(/\s+/g);
19
+ if (!Array.isArray(node.properties.class)) node.properties.class = [];
20
+ const targets = Array.isArray(className) ? className : className.split(/\s+/g);
21
+ for (const c of targets) if (c && !node.properties.class.includes(c)) node.properties.class.push(c);
22
+ return node;
57
23
  }
58
24
 
59
- function splitLines(code, preserveEnding = false) {
60
- if (code.length === 0) {
61
- return [["", 0]];
62
- }
63
- const parts = code.split(/(\r?\n)/g);
64
- let index = 0;
65
- const lines = [];
66
- for (let i = 0; i < parts.length; i += 2) {
67
- const line = preserveEnding ? parts[i] + (parts[i + 1] || "") : parts[i];
68
- lines.push([line, index]);
69
- index += parts[i].length;
70
- index += parts[i + 1]?.length || 0;
71
- }
72
- return lines;
73
- }
25
+ //#endregion
26
+ //#region src/utils/strings.ts
27
+ /**
28
+ * Creates a converter between index and position in a code block.
29
+ *
30
+ * Overflow/underflow are unchecked.
31
+ */
74
32
  function createPositionConverter(code) {
75
- const lines = splitLines(code, true).map(([line]) => line);
76
- function indexToPos(index) {
77
- if (index === code.length) {
78
- return {
79
- line: lines.length - 1,
80
- character: lines[lines.length - 1].length
81
- };
82
- }
83
- let character = index;
84
- let line = 0;
85
- for (const lineText of lines) {
86
- if (character < lineText.length)
87
- break;
88
- character -= lineText.length;
89
- line++;
90
- }
91
- return { line, character };
92
- }
93
- function posToIndex(line, character) {
94
- let index = 0;
95
- for (let i = 0; i < line; i++)
96
- index += lines[i].length;
97
- index += character;
98
- return index;
99
- }
100
- return {
101
- lines,
102
- indexToPos,
103
- posToIndex
104
- };
105
- }
33
+ const lines = splitLines$1(code, true).map(([line]) => line);
34
+ function indexToPos(index) {
35
+ if (index === code.length) return {
36
+ line: lines.length - 1,
37
+ character: lines[lines.length - 1].length
38
+ };
39
+ let character = index;
40
+ let line = 0;
41
+ for (const lineText of lines) {
42
+ if (character < lineText.length) break;
43
+ character -= lineText.length;
44
+ line++;
45
+ }
46
+ return {
47
+ line,
48
+ character
49
+ };
50
+ }
51
+ function posToIndex(line, character) {
52
+ let index = 0;
53
+ for (let i = 0; i < line; i++) index += lines[i].length;
54
+ index += character;
55
+ return index;
56
+ }
57
+ return {
58
+ lines,
59
+ indexToPos,
60
+ posToIndex
61
+ };
62
+ }
63
+ /**
64
+ * Guess embedded languages from given code and highlighter.
65
+ *
66
+ * When highlighter is provided, only bundled languages will be included.
67
+ *
68
+ * @param code - The code string to analyze
69
+ * @param _lang - The primary language of the code (currently unused)
70
+ * @param highlighter - Optional highlighter instance to validate languages
71
+ * @returns Array of detected language identifiers
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * // Detects 'javascript' from Vue SFC
76
+ * guessEmbeddedLanguages('<script lang="javascript">')
77
+ *
78
+ * // Detects 'python' from markdown code block
79
+ * guessEmbeddedLanguages('```python\nprint("hi")\n```')
80
+ * ```
81
+ */
106
82
  function guessEmbeddedLanguages(code, _lang, highlighter) {
107
- const langs = /* @__PURE__ */ new Set();
108
- for (const match of code.matchAll(/:?lang=["']([^"']+)["']/g)) {
109
- const lang = match[1].toLowerCase().trim();
110
- if (lang)
111
- langs.add(lang);
112
- }
113
- for (const match of code.matchAll(/(?:```|~~~)([\w-]+)/g)) {
114
- const lang = match[1].toLowerCase().trim();
115
- if (lang)
116
- langs.add(lang);
117
- }
118
- for (const match of code.matchAll(/\\begin\{([\w-]+)\}/g)) {
119
- const lang = match[1].toLowerCase().trim();
120
- if (lang)
121
- langs.add(lang);
122
- }
123
- for (const match of code.matchAll(/<script\s+(?:type|lang)=["']([^"']+)["']/gi)) {
124
- const fullType = match[1].toLowerCase().trim();
125
- const lang = fullType.includes("/") ? fullType.split("/").pop() : fullType;
126
- if (lang)
127
- langs.add(lang);
128
- }
129
- if (!highlighter)
130
- return Array.from(langs);
131
- const bundle = highlighter.getBundledLanguages();
132
- return Array.from(langs).filter((l) => l && bundle[l]);
83
+ const langs = /* @__PURE__ */ new Set();
84
+ for (const match of code.matchAll(/:?lang=["']([^"']+)["']/g)) {
85
+ const lang = match[1].toLowerCase().trim();
86
+ if (lang) langs.add(lang);
87
+ }
88
+ for (const match of code.matchAll(/(?:```|~~~)([\w-]+)/g)) {
89
+ const lang = match[1].toLowerCase().trim();
90
+ if (lang) langs.add(lang);
91
+ }
92
+ for (const match of code.matchAll(/\\begin\{([\w-]+)\}/g)) {
93
+ const lang = match[1].toLowerCase().trim();
94
+ if (lang) langs.add(lang);
95
+ }
96
+ for (const match of code.matchAll(/<script\s+(?:type|lang)=["']([^"']+)["']/gi)) {
97
+ const fullType = match[1].toLowerCase().trim();
98
+ const lang = fullType.includes("/") ? fullType.split("/").pop() : fullType;
99
+ if (lang) langs.add(lang);
100
+ }
101
+ if (!highlighter) return Array.from(langs);
102
+ const bundle = highlighter.getBundledLanguages();
103
+ return Array.from(langs).filter((l) => l && bundle[l]);
133
104
  }
134
105
 
106
+ //#endregion
107
+ //#region src/utils/constants.ts
135
108
  const DEFAULT_COLOR_LIGHT_DARK = "light-dark()";
136
109
  const COLOR_KEYS = ["color", "background-color"];
137
110
 
111
+ //#endregion
112
+ //#region src/utils/tokens.ts
113
+ /**
114
+ * Split a token into multiple tokens by given offsets.
115
+ *
116
+ * The offsets are relative to the token, and should be sorted.
117
+ */
138
118
  function splitToken(token, offsets) {
139
- let lastOffset = 0;
140
- const tokens = [];
141
- for (const offset of offsets) {
142
- if (offset > lastOffset) {
143
- tokens.push({
144
- ...token,
145
- content: token.content.slice(lastOffset, offset),
146
- offset: token.offset + lastOffset
147
- });
148
- }
149
- lastOffset = offset;
150
- }
151
- if (lastOffset < token.content.length) {
152
- tokens.push({
153
- ...token,
154
- content: token.content.slice(lastOffset),
155
- offset: token.offset + lastOffset
156
- });
157
- }
158
- return tokens;
159
- }
119
+ let lastOffset = 0;
120
+ const tokens = [];
121
+ for (const offset of offsets) {
122
+ if (offset > lastOffset) tokens.push({
123
+ ...token,
124
+ content: token.content.slice(lastOffset, offset),
125
+ offset: token.offset + lastOffset
126
+ });
127
+ lastOffset = offset;
128
+ }
129
+ if (lastOffset < token.content.length) tokens.push({
130
+ ...token,
131
+ content: token.content.slice(lastOffset),
132
+ offset: token.offset + lastOffset
133
+ });
134
+ return tokens;
135
+ }
136
+ /**
137
+ * Split 2D tokens array by given breakpoints.
138
+ */
160
139
  function splitTokens(tokens, breakpoints) {
161
- const sorted = Array.from(breakpoints instanceof Set ? breakpoints : new Set(breakpoints)).sort((a, b) => a - b);
162
- if (!sorted.length)
163
- return tokens;
164
- return tokens.map((line) => {
165
- return line.flatMap((token) => {
166
- const breakpointsInToken = sorted.filter((i) => token.offset < i && i < token.offset + token.content.length).map((i) => i - token.offset).sort((a, b) => a - b);
167
- if (!breakpointsInToken.length)
168
- return token;
169
- return splitToken(token, breakpointsInToken);
170
- });
171
- });
140
+ const sorted = Array.from(breakpoints instanceof Set ? breakpoints : new Set(breakpoints)).sort((a, b) => a - b);
141
+ if (!sorted.length) return tokens;
142
+ return tokens.map((line) => {
143
+ return line.flatMap((token) => {
144
+ const breakpointsInToken = sorted.filter((i) => token.offset < i && i < token.offset + token.content.length).map((i) => i - token.offset).sort((a, b) => a - b);
145
+ if (!breakpointsInToken.length) return token;
146
+ return splitToken(token, breakpointsInToken);
147
+ });
148
+ });
172
149
  }
173
150
  function flatTokenVariants(merged, variantsOrder, cssVariablePrefix, defaultColor, colorsRendering = "css-vars") {
174
- const token = {
175
- content: merged.content,
176
- explanation: merged.explanation,
177
- offset: merged.offset
178
- };
179
- const styles = variantsOrder.map((t) => getTokenStyleObject(merged.variants[t]));
180
- const styleKeys = new Set(styles.flatMap((t) => Object.keys(t)));
181
- const mergedStyles = {};
182
- const varKey = (idx, key) => {
183
- const keyName = key === "color" ? "" : key === "background-color" ? "-bg" : `-${key}`;
184
- return cssVariablePrefix + variantsOrder[idx] + (key === "color" ? "" : keyName);
185
- };
186
- styles.forEach((cur, idx) => {
187
- for (const key of styleKeys) {
188
- const value = cur[key] || "inherit";
189
- if (idx === 0 && defaultColor && COLOR_KEYS.includes(key)) {
190
- if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && styles.length > 1) {
191
- const lightIndex = variantsOrder.findIndex((t) => t === "light");
192
- const darkIndex = variantsOrder.findIndex((t) => t === "dark");
193
- if (lightIndex === -1 || darkIndex === -1)
194
- throw new ShikiError$1('When using `defaultColor: "light-dark()"`, you must provide both `light` and `dark` themes');
195
- const lightValue = styles[lightIndex][key] || "inherit";
196
- const darkValue = styles[darkIndex][key] || "inherit";
197
- mergedStyles[key] = `light-dark(${lightValue}, ${darkValue})`;
198
- if (colorsRendering === "css-vars")
199
- mergedStyles[varKey(idx, key)] = value;
200
- } else {
201
- mergedStyles[key] = value;
202
- }
203
- } else {
204
- if (colorsRendering === "css-vars")
205
- mergedStyles[varKey(idx, key)] = value;
206
- }
207
- }
208
- });
209
- token.htmlStyle = mergedStyles;
210
- return token;
151
+ const token = {
152
+ content: merged.content,
153
+ explanation: merged.explanation,
154
+ offset: merged.offset
155
+ };
156
+ const styles = variantsOrder.map((t) => getTokenStyleObject(merged.variants[t]));
157
+ const styleKeys = new Set(styles.flatMap((t) => Object.keys(t)));
158
+ const mergedStyles = {};
159
+ const varKey = (idx, key) => {
160
+ const keyName = key === "color" ? "" : key === "background-color" ? "-bg" : `-${key}`;
161
+ return cssVariablePrefix + variantsOrder[idx] + (key === "color" ? "" : keyName);
162
+ };
163
+ styles.forEach((cur, idx) => {
164
+ for (const key of styleKeys) {
165
+ const value = cur[key] || "inherit";
166
+ if (idx === 0 && defaultColor && COLOR_KEYS.includes(key)) if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && styles.length > 1) {
167
+ const lightIndex = variantsOrder.findIndex((t) => t === "light");
168
+ const darkIndex = variantsOrder.findIndex((t) => t === "dark");
169
+ if (lightIndex === -1 || darkIndex === -1) throw new ShikiError$1("When using `defaultColor: \"light-dark()\"`, you must provide both `light` and `dark` themes");
170
+ mergedStyles[key] = `light-dark(${styles[lightIndex][key] || "inherit"}, ${styles[darkIndex][key] || "inherit"})`;
171
+ if (colorsRendering === "css-vars") mergedStyles[varKey(idx, key)] = value;
172
+ } else mergedStyles[key] = value;
173
+ else if (colorsRendering === "css-vars") mergedStyles[varKey(idx, key)] = value;
174
+ }
175
+ });
176
+ token.htmlStyle = mergedStyles;
177
+ return token;
211
178
  }
212
179
  function getTokenStyleObject(token) {
213
- const styles = {};
214
- if (token.color)
215
- styles.color = token.color;
216
- if (token.bgColor)
217
- styles["background-color"] = token.bgColor;
218
- if (token.fontStyle) {
219
- if (token.fontStyle & FontStyle.Italic)
220
- styles["font-style"] = "italic";
221
- if (token.fontStyle & FontStyle.Bold)
222
- styles["font-weight"] = "bold";
223
- const decorations = [];
224
- if (token.fontStyle & FontStyle.Underline)
225
- decorations.push("underline");
226
- if (token.fontStyle & FontStyle.Strikethrough)
227
- decorations.push("line-through");
228
- if (decorations.length)
229
- styles["text-decoration"] = decorations.join(" ");
230
- }
231
- return styles;
180
+ const styles = {};
181
+ if (token.color) styles.color = token.color;
182
+ if (token.bgColor) styles["background-color"] = token.bgColor;
183
+ if (token.fontStyle) {
184
+ if (token.fontStyle & FontStyle.Italic) styles["font-style"] = "italic";
185
+ if (token.fontStyle & FontStyle.Bold) styles["font-weight"] = "bold";
186
+ const decorations = [];
187
+ if (token.fontStyle & FontStyle.Underline) decorations.push("underline");
188
+ if (token.fontStyle & FontStyle.Strikethrough) decorations.push("line-through");
189
+ if (decorations.length) styles["text-decoration"] = decorations.join(" ");
190
+ }
191
+ return styles;
232
192
  }
233
193
  function stringifyTokenStyle(token) {
234
- if (typeof token === "string")
235
- return token;
236
- return Object.entries(token).map(([key, value]) => `${key}:${value}`).join(";");
237
- }
238
-
239
- const _grammarStateMap = /* @__PURE__ */ new WeakMap();
240
- function setLastGrammarStateToMap(keys, state) {
241
- _grammarStateMap.set(keys, state);
242
- }
243
- function getLastGrammarStateFromMap(keys) {
244
- return _grammarStateMap.get(keys);
245
- }
246
- class GrammarState {
247
- /**
248
- * Theme to Stack mapping
249
- */
250
- _stacks = {};
251
- lang;
252
- get themes() {
253
- return Object.keys(this._stacks);
254
- }
255
- get theme() {
256
- return this.themes[0];
257
- }
258
- get _stack() {
259
- return this._stacks[this.theme];
260
- }
261
- /**
262
- * Static method to create a initial grammar state.
263
- */
264
- static initial(lang, themes) {
265
- return new GrammarState(
266
- Object.fromEntries(toArray(themes).map((theme) => [theme, INITIAL])),
267
- lang
268
- );
269
- }
270
- constructor(...args) {
271
- if (args.length === 2) {
272
- const [stacksMap, lang] = args;
273
- this.lang = lang;
274
- this._stacks = stacksMap;
275
- } else {
276
- const [stack, lang, theme] = args;
277
- this.lang = lang;
278
- this._stacks = { [theme]: stack };
279
- }
280
- }
281
- /**
282
- * Get the internal stack object.
283
- * @internal
284
- */
285
- getInternalStack(theme = this.theme) {
286
- return this._stacks[theme];
287
- }
288
- getScopes(theme = this.theme) {
289
- return getScopes(this._stacks[theme]);
290
- }
291
- toJSON() {
292
- return {
293
- lang: this.lang,
294
- theme: this.theme,
295
- themes: this.themes,
296
- scopes: this.getScopes()
297
- };
298
- }
299
- }
300
- function getScopes(stack) {
301
- const scopes = [];
302
- const visited = /* @__PURE__ */ new Set();
303
- function pushScope(stack2) {
304
- if (visited.has(stack2))
305
- return;
306
- visited.add(stack2);
307
- const name = stack2?.nameScopesList?.scopeName;
308
- if (name)
309
- scopes.push(name);
310
- if (stack2.parent)
311
- pushScope(stack2.parent);
312
- }
313
- pushScope(stack);
314
- return scopes;
315
- }
316
- function getGrammarStack(state, theme) {
317
- if (!(state instanceof GrammarState))
318
- throw new ShikiError$1("Invalid grammar state");
319
- return state.getInternalStack(theme);
194
+ if (typeof token === "string") return token;
195
+ return Object.entries(token).map(([key, value]) => `${key}:${value}`).join(";");
320
196
  }
321
197
 
198
+ //#endregion
199
+ //#region src/transformer-decorations.ts
200
+ /**
201
+ * A built-in transformer to add decorations to the highlighted code.
202
+ */
322
203
  function transformerDecorations() {
323
- const map = /* @__PURE__ */ new WeakMap();
324
- function getContext(shiki) {
325
- if (!map.has(shiki.meta)) {
326
- let normalizePosition = function(p) {
327
- if (typeof p === "number") {
328
- if (p < 0 || p > shiki.source.length)
329
- throw new ShikiError$1(`Invalid decoration offset: ${p}. Code length: ${shiki.source.length}`);
330
- return {
331
- ...converter.indexToPos(p),
332
- offset: p
333
- };
334
- } else {
335
- const line = converter.lines[p.line];
336
- if (line === void 0)
337
- throw new ShikiError$1(`Invalid decoration position ${JSON.stringify(p)}. Lines length: ${converter.lines.length}`);
338
- let character = p.character;
339
- if (character < 0)
340
- character = line.length + character;
341
- if (character < 0 || character > line.length)
342
- throw new ShikiError$1(`Invalid decoration position ${JSON.stringify(p)}. Line ${p.line} length: ${line.length}`);
343
- return {
344
- ...p,
345
- character,
346
- offset: converter.posToIndex(p.line, character)
347
- };
348
- }
349
- };
350
- const converter = createPositionConverter(shiki.source);
351
- const decorations = (shiki.options.decorations || []).map((d) => ({
352
- ...d,
353
- start: normalizePosition(d.start),
354
- end: normalizePosition(d.end)
355
- }));
356
- verifyIntersections(decorations);
357
- map.set(shiki.meta, {
358
- decorations,
359
- converter,
360
- source: shiki.source
361
- });
362
- }
363
- return map.get(shiki.meta);
364
- }
365
- return {
366
- name: "shiki:decorations",
367
- tokens(tokens) {
368
- if (!this.options.decorations?.length)
369
- return;
370
- const ctx = getContext(this);
371
- const breakpoints = ctx.decorations.flatMap((d) => [d.start.offset, d.end.offset]);
372
- const splitted = splitTokens(tokens, breakpoints);
373
- return splitted;
374
- },
375
- code(codeEl) {
376
- if (!this.options.decorations?.length)
377
- return;
378
- const ctx = getContext(this);
379
- const lines = Array.from(codeEl.children).filter((i) => i.type === "element" && i.tagName === "span");
380
- if (lines.length !== ctx.converter.lines.length)
381
- throw new ShikiError$1(`Number of lines in code element (${lines.length}) does not match the number of lines in the source (${ctx.converter.lines.length}). Failed to apply decorations.`);
382
- function applyLineSection(line, start, end, decoration) {
383
- const lineEl = lines[line];
384
- let text = "";
385
- let startIndex = -1;
386
- let endIndex = -1;
387
- if (start === 0)
388
- startIndex = 0;
389
- if (end === 0)
390
- endIndex = 0;
391
- if (end === Number.POSITIVE_INFINITY)
392
- endIndex = lineEl.children.length;
393
- if (startIndex === -1 || endIndex === -1) {
394
- for (let i = 0; i < lineEl.children.length; i++) {
395
- text += stringify(lineEl.children[i]);
396
- if (startIndex === -1 && text.length === start)
397
- startIndex = i + 1;
398
- if (endIndex === -1 && text.length === end)
399
- endIndex = i + 1;
400
- }
401
- }
402
- if (startIndex === -1)
403
- throw new ShikiError$1(`Failed to find start index for decoration ${JSON.stringify(decoration.start)}`);
404
- if (endIndex === -1)
405
- throw new ShikiError$1(`Failed to find end index for decoration ${JSON.stringify(decoration.end)}`);
406
- const children = lineEl.children.slice(startIndex, endIndex);
407
- if (!decoration.alwaysWrap && children.length === lineEl.children.length) {
408
- applyDecoration(lineEl, decoration, "line");
409
- } else if (!decoration.alwaysWrap && children.length === 1 && children[0].type === "element") {
410
- applyDecoration(children[0], decoration, "token");
411
- } else {
412
- const wrapper = {
413
- type: "element",
414
- tagName: "span",
415
- properties: {},
416
- children
417
- };
418
- applyDecoration(wrapper, decoration, "wrapper");
419
- lineEl.children.splice(startIndex, children.length, wrapper);
420
- }
421
- }
422
- function applyLine(line, decoration) {
423
- lines[line] = applyDecoration(lines[line], decoration, "line");
424
- }
425
- function applyDecoration(el, decoration, type) {
426
- const properties = decoration.properties || {};
427
- const transform = decoration.transform || ((i) => i);
428
- el.tagName = decoration.tagName || "span";
429
- el.properties = {
430
- ...el.properties,
431
- ...properties,
432
- class: el.properties.class
433
- };
434
- if (decoration.properties?.class)
435
- addClassToHast(el, decoration.properties.class);
436
- el = transform(el, type) || el;
437
- return el;
438
- }
439
- const lineApplies = [];
440
- const sorted = ctx.decorations.sort((a, b) => b.start.offset - a.start.offset || a.end.offset - b.end.offset);
441
- for (const decoration of sorted) {
442
- const { start, end } = decoration;
443
- if (start.line === end.line) {
444
- applyLineSection(start.line, start.character, end.character, decoration);
445
- } else if (start.line < end.line) {
446
- applyLineSection(start.line, start.character, Number.POSITIVE_INFINITY, decoration);
447
- for (let i = start.line + 1; i < end.line; i++)
448
- lineApplies.unshift(() => applyLine(i, decoration));
449
- applyLineSection(end.line, 0, end.character, decoration);
450
- }
451
- }
452
- lineApplies.forEach((i) => i());
453
- }
454
- };
204
+ const map = /* @__PURE__ */ new WeakMap();
205
+ function getContext(shiki) {
206
+ if (!map.has(shiki.meta)) {
207
+ const converter = createPositionConverter(shiki.source);
208
+ function normalizePosition(p) {
209
+ if (typeof p === "number") {
210
+ if (p < 0 || p > shiki.source.length) throw new ShikiError$1(`Invalid decoration offset: ${p}. Code length: ${shiki.source.length}`);
211
+ return {
212
+ ...converter.indexToPos(p),
213
+ offset: p
214
+ };
215
+ } else {
216
+ const line = converter.lines[p.line];
217
+ if (line === void 0) throw new ShikiError$1(`Invalid decoration position ${JSON.stringify(p)}. Lines length: ${converter.lines.length}`);
218
+ let character = p.character;
219
+ if (character < 0) character = line.length + character;
220
+ if (character < 0 || character > line.length) throw new ShikiError$1(`Invalid decoration position ${JSON.stringify(p)}. Line ${p.line} length: ${line.length}`);
221
+ return {
222
+ ...p,
223
+ character,
224
+ offset: converter.posToIndex(p.line, character)
225
+ };
226
+ }
227
+ }
228
+ const decorations = (shiki.options.decorations || []).map((d) => ({
229
+ ...d,
230
+ start: normalizePosition(d.start),
231
+ end: normalizePosition(d.end)
232
+ }));
233
+ verifyIntersections(decorations);
234
+ map.set(shiki.meta, {
235
+ decorations,
236
+ converter,
237
+ source: shiki.source
238
+ });
239
+ }
240
+ return map.get(shiki.meta);
241
+ }
242
+ return {
243
+ name: "shiki:decorations",
244
+ tokens(tokens) {
245
+ if (!this.options.decorations?.length) return;
246
+ return splitTokens(tokens, getContext(this).decorations.flatMap((d) => [d.start.offset, d.end.offset]));
247
+ },
248
+ code(codeEl) {
249
+ if (!this.options.decorations?.length) return;
250
+ const ctx = getContext(this);
251
+ const lines = Array.from(codeEl.children).filter((i) => i.type === "element" && i.tagName === "span");
252
+ if (lines.length !== ctx.converter.lines.length) throw new ShikiError$1(`Number of lines in code element (${lines.length}) does not match the number of lines in the source (${ctx.converter.lines.length}). Failed to apply decorations.`);
253
+ function applyLineSection(line, start, end, decoration) {
254
+ const lineEl = lines[line];
255
+ let text = "";
256
+ let startIndex = -1;
257
+ let endIndex = -1;
258
+ if (start === 0) startIndex = 0;
259
+ if (end === 0) endIndex = 0;
260
+ if (end === Number.POSITIVE_INFINITY) endIndex = lineEl.children.length;
261
+ if (startIndex === -1 || endIndex === -1) for (let i = 0; i < lineEl.children.length; i++) {
262
+ text += stringify(lineEl.children[i]);
263
+ if (startIndex === -1 && text.length === start) startIndex = i + 1;
264
+ if (endIndex === -1 && text.length === end) endIndex = i + 1;
265
+ }
266
+ if (startIndex === -1) throw new ShikiError$1(`Failed to find start index for decoration ${JSON.stringify(decoration.start)}`);
267
+ if (endIndex === -1) throw new ShikiError$1(`Failed to find end index for decoration ${JSON.stringify(decoration.end)}`);
268
+ const children = lineEl.children.slice(startIndex, endIndex);
269
+ if (!decoration.alwaysWrap && children.length === lineEl.children.length) applyDecoration(lineEl, decoration, "line");
270
+ else if (!decoration.alwaysWrap && children.length === 1 && children[0].type === "element") applyDecoration(children[0], decoration, "token");
271
+ else {
272
+ const wrapper = {
273
+ type: "element",
274
+ tagName: "span",
275
+ properties: {},
276
+ children
277
+ };
278
+ applyDecoration(wrapper, decoration, "wrapper");
279
+ lineEl.children.splice(startIndex, children.length, wrapper);
280
+ }
281
+ }
282
+ function applyLine(line, decoration) {
283
+ lines[line] = applyDecoration(lines[line], decoration, "line");
284
+ }
285
+ function applyDecoration(el, decoration, type) {
286
+ const properties = decoration.properties || {};
287
+ const transform = decoration.transform || ((i) => i);
288
+ el.tagName = decoration.tagName || "span";
289
+ el.properties = {
290
+ ...el.properties,
291
+ ...properties,
292
+ class: el.properties.class
293
+ };
294
+ if (decoration.properties?.class) addClassToHast(el, decoration.properties.class);
295
+ el = transform(el, type) || el;
296
+ return el;
297
+ }
298
+ const lineApplies = [];
299
+ const sorted = ctx.decorations.sort((a, b) => b.start.offset - a.start.offset || a.end.offset - b.end.offset);
300
+ for (const decoration of sorted) {
301
+ const { start, end } = decoration;
302
+ if (start.line === end.line) applyLineSection(start.line, start.character, end.character, decoration);
303
+ else if (start.line < end.line) {
304
+ applyLineSection(start.line, start.character, Number.POSITIVE_INFINITY, decoration);
305
+ for (let i = start.line + 1; i < end.line; i++) lineApplies.unshift(() => applyLine(i, decoration));
306
+ applyLineSection(end.line, 0, end.character, decoration);
307
+ }
308
+ }
309
+ lineApplies.forEach((i) => i());
310
+ }
311
+ };
455
312
  }
456
313
  function verifyIntersections(items) {
457
- for (let i = 0; i < items.length; i++) {
458
- const foo = items[i];
459
- if (foo.start.offset > foo.end.offset)
460
- throw new ShikiError$1(`Invalid decoration range: ${JSON.stringify(foo.start)} - ${JSON.stringify(foo.end)}`);
461
- for (let j = i + 1; j < items.length; j++) {
462
- const bar = items[j];
463
- const isFooHasBarStart = foo.start.offset <= bar.start.offset && bar.start.offset < foo.end.offset;
464
- const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset <= foo.end.offset;
465
- const isBarHasFooStart = bar.start.offset <= foo.start.offset && foo.start.offset < bar.end.offset;
466
- const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset <= bar.end.offset;
467
- if (isFooHasBarStart || isFooHasBarEnd || isBarHasFooStart || isBarHasFooEnd) {
468
- if (isFooHasBarStart && isFooHasBarEnd)
469
- continue;
470
- if (isBarHasFooStart && isBarHasFooEnd)
471
- continue;
472
- if (isBarHasFooStart && foo.start.offset === foo.end.offset)
473
- continue;
474
- if (isFooHasBarEnd && bar.start.offset === bar.end.offset)
475
- continue;
476
- throw new ShikiError$1(`Decorations ${JSON.stringify(foo.start)} and ${JSON.stringify(bar.start)} intersect.`);
477
- }
478
- }
479
- }
314
+ for (let i = 0; i < items.length; i++) {
315
+ const foo = items[i];
316
+ if (foo.start.offset > foo.end.offset) throw new ShikiError$1(`Invalid decoration range: ${JSON.stringify(foo.start)} - ${JSON.stringify(foo.end)}`);
317
+ for (let j = i + 1; j < items.length; j++) {
318
+ const bar = items[j];
319
+ const isFooHasBarStart = foo.start.offset <= bar.start.offset && bar.start.offset < foo.end.offset;
320
+ const isFooHasBarEnd = foo.start.offset < bar.end.offset && bar.end.offset <= foo.end.offset;
321
+ const isBarHasFooStart = bar.start.offset <= foo.start.offset && foo.start.offset < bar.end.offset;
322
+ const isBarHasFooEnd = bar.start.offset < foo.end.offset && foo.end.offset <= bar.end.offset;
323
+ if (isFooHasBarStart || isFooHasBarEnd || isBarHasFooStart || isBarHasFooEnd) {
324
+ if (isFooHasBarStart && isFooHasBarEnd) continue;
325
+ if (isBarHasFooStart && isBarHasFooEnd) continue;
326
+ if (isBarHasFooStart && foo.start.offset === foo.end.offset) continue;
327
+ if (isFooHasBarEnd && bar.start.offset === bar.end.offset) continue;
328
+ throw new ShikiError$1(`Decorations ${JSON.stringify(foo.start)} and ${JSON.stringify(bar.start)} intersect.`);
329
+ }
330
+ }
331
+ }
480
332
  }
481
333
  function stringify(el) {
482
- if (el.type === "text")
483
- return el.value;
484
- if (el.type === "element")
485
- return el.children.map(stringify).join("");
486
- return "";
334
+ if (el.type === "text") return el.value;
335
+ if (el.type === "element") return el.children.map(stringify).join("");
336
+ return "";
487
337
  }
488
338
 
489
- const builtInTransformers = [
490
- /* @__PURE__ */ transformerDecorations()
491
- ];
339
+ //#endregion
340
+ //#region src/highlight/_get-transformers.ts
341
+ const builtInTransformers = [/* @__PURE__ */ transformerDecorations()];
492
342
  function getTransformers(options) {
493
- const transformers = sortTransformersByEnforcement(options.transformers || []);
494
- return [
495
- ...transformers.pre,
496
- ...transformers.normal,
497
- ...transformers.post,
498
- ...builtInTransformers
499
- ];
343
+ const transformers = sortTransformersByEnforcement(options.transformers || []);
344
+ return [
345
+ ...transformers.pre,
346
+ ...transformers.normal,
347
+ ...transformers.post,
348
+ ...builtInTransformers
349
+ ];
500
350
  }
501
351
  function sortTransformersByEnforcement(transformers) {
502
- const pre = [];
503
- const post = [];
504
- const normal = [];
505
- for (const transformer of transformers) {
506
- switch (transformer.enforce) {
507
- case "pre":
508
- pre.push(transformer);
509
- break;
510
- case "post":
511
- post.push(transformer);
512
- break;
513
- default:
514
- normal.push(transformer);
515
- }
516
- }
517
- return { pre, post, normal };
352
+ const pre = [];
353
+ const post = [];
354
+ const normal = [];
355
+ for (const transformer of transformers) switch (transformer.enforce) {
356
+ case "pre":
357
+ pre.push(transformer);
358
+ break;
359
+ case "post":
360
+ post.push(transformer);
361
+ break;
362
+ default: normal.push(transformer);
363
+ }
364
+ return {
365
+ pre,
366
+ post,
367
+ normal
368
+ };
518
369
  }
519
370
 
520
- // src/colors.ts
371
+ //#endregion
372
+ //#region ../../node_modules/.pnpm/ansi-sequence-parser@1.1.3/node_modules/ansi-sequence-parser/dist/index.js
521
373
  var namedColors = [
522
- "black",
523
- "red",
524
- "green",
525
- "yellow",
526
- "blue",
527
- "magenta",
528
- "cyan",
529
- "white",
530
- "brightBlack",
531
- "brightRed",
532
- "brightGreen",
533
- "brightYellow",
534
- "brightBlue",
535
- "brightMagenta",
536
- "brightCyan",
537
- "brightWhite"
374
+ "black",
375
+ "red",
376
+ "green",
377
+ "yellow",
378
+ "blue",
379
+ "magenta",
380
+ "cyan",
381
+ "white",
382
+ "brightBlack",
383
+ "brightRed",
384
+ "brightGreen",
385
+ "brightYellow",
386
+ "brightBlue",
387
+ "brightMagenta",
388
+ "brightCyan",
389
+ "brightWhite"
538
390
  ];
539
-
540
- // src/decorations.ts
541
391
  var decorations = {
542
- 1: "bold",
543
- 2: "dim",
544
- 3: "italic",
545
- 4: "underline",
546
- 7: "reverse",
547
- 8: "hidden",
548
- 9: "strikethrough"
392
+ 1: "bold",
393
+ 2: "dim",
394
+ 3: "italic",
395
+ 4: "underline",
396
+ 7: "reverse",
397
+ 8: "hidden",
398
+ 9: "strikethrough"
549
399
  };
550
-
551
- // src/parser.ts
552
400
  function findSequence(value, position) {
553
- const nextEscape = value.indexOf("\x1B", position);
554
- if (nextEscape !== -1) {
555
- if (value[nextEscape + 1] === "[") {
556
- const nextClose = value.indexOf("m", nextEscape);
557
- if (nextClose !== -1) {
558
- return {
559
- sequence: value.substring(nextEscape + 2, nextClose).split(";"),
560
- startPosition: nextEscape,
561
- position: nextClose + 1
562
- };
563
- }
564
- }
565
- }
566
- return {
567
- position: value.length
568
- };
401
+ const nextEscape = value.indexOf("\x1B", position);
402
+ if (nextEscape !== -1) {
403
+ if (value[nextEscape + 1] === "[") {
404
+ const nextClose = value.indexOf("m", nextEscape);
405
+ if (nextClose !== -1) return {
406
+ sequence: value.substring(nextEscape + 2, nextClose).split(";"),
407
+ startPosition: nextEscape,
408
+ position: nextClose + 1
409
+ };
410
+ }
411
+ }
412
+ return { position: value.length };
569
413
  }
570
414
  function parseColor(sequence) {
571
- const colorMode = sequence.shift();
572
- if (colorMode === "2") {
573
- const rgb = sequence.splice(0, 3).map((x) => Number.parseInt(x));
574
- if (rgb.length !== 3 || rgb.some((x) => Number.isNaN(x)))
575
- return;
576
- return {
577
- type: "rgb",
578
- rgb
579
- };
580
- } else if (colorMode === "5") {
581
- const index = sequence.shift();
582
- if (index) {
583
- return { type: "table", index: Number(index) };
584
- }
585
- }
415
+ const colorMode = sequence.shift();
416
+ if (colorMode === "2") {
417
+ const rgb = sequence.splice(0, 3).map((x) => Number.parseInt(x));
418
+ if (rgb.length !== 3 || rgb.some((x) => Number.isNaN(x))) return;
419
+ return {
420
+ type: "rgb",
421
+ rgb
422
+ };
423
+ } else if (colorMode === "5") {
424
+ const index = sequence.shift();
425
+ if (index) return {
426
+ type: "table",
427
+ index: Number(index)
428
+ };
429
+ }
586
430
  }
587
431
  function parseSequence(sequence) {
588
- const commands = [];
589
- while (sequence.length > 0) {
590
- const code = sequence.shift();
591
- if (!code)
592
- continue;
593
- const codeInt = Number.parseInt(code);
594
- if (Number.isNaN(codeInt))
595
- continue;
596
- if (codeInt === 0) {
597
- commands.push({ type: "resetAll" });
598
- } else if (codeInt <= 9) {
599
- const decoration = decorations[codeInt];
600
- if (decoration) {
601
- commands.push({
602
- type: "setDecoration",
603
- value: decorations[codeInt]
604
- });
605
- }
606
- } else if (codeInt <= 29) {
607
- const decoration = decorations[codeInt - 20];
608
- if (decoration) {
609
- commands.push({
610
- type: "resetDecoration",
611
- value: decoration
612
- });
613
- if (decoration === "dim") {
614
- commands.push({
615
- type: "resetDecoration",
616
- value: "bold"
617
- });
618
- }
619
- }
620
- } else if (codeInt <= 37) {
621
- commands.push({
622
- type: "setForegroundColor",
623
- value: { type: "named", name: namedColors[codeInt - 30] }
624
- });
625
- } else if (codeInt === 38) {
626
- const color = parseColor(sequence);
627
- if (color) {
628
- commands.push({
629
- type: "setForegroundColor",
630
- value: color
631
- });
632
- }
633
- } else if (codeInt === 39) {
634
- commands.push({
635
- type: "resetForegroundColor"
636
- });
637
- } else if (codeInt <= 47) {
638
- commands.push({
639
- type: "setBackgroundColor",
640
- value: { type: "named", name: namedColors[codeInt - 40] }
641
- });
642
- } else if (codeInt === 48) {
643
- const color = parseColor(sequence);
644
- if (color) {
645
- commands.push({
646
- type: "setBackgroundColor",
647
- value: color
648
- });
649
- }
650
- } else if (codeInt === 49) {
651
- commands.push({
652
- type: "resetBackgroundColor"
653
- });
654
- } else if (codeInt === 53) {
655
- commands.push({
656
- type: "setDecoration",
657
- value: "overline"
658
- });
659
- } else if (codeInt === 55) {
660
- commands.push({
661
- type: "resetDecoration",
662
- value: "overline"
663
- });
664
- } else if (codeInt >= 90 && codeInt <= 97) {
665
- commands.push({
666
- type: "setForegroundColor",
667
- value: { type: "named", name: namedColors[codeInt - 90 + 8] }
668
- });
669
- } else if (codeInt >= 100 && codeInt <= 107) {
670
- commands.push({
671
- type: "setBackgroundColor",
672
- value: { type: "named", name: namedColors[codeInt - 100 + 8] }
673
- });
674
- }
675
- }
676
- return commands;
432
+ const commands = [];
433
+ while (sequence.length > 0) {
434
+ const code = sequence.shift();
435
+ if (!code) continue;
436
+ const codeInt = Number.parseInt(code);
437
+ if (Number.isNaN(codeInt)) continue;
438
+ if (codeInt === 0) commands.push({ type: "resetAll" });
439
+ else if (codeInt <= 9) {
440
+ if (decorations[codeInt]) commands.push({
441
+ type: "setDecoration",
442
+ value: decorations[codeInt]
443
+ });
444
+ } else if (codeInt <= 29) {
445
+ const decoration = decorations[codeInt - 20];
446
+ if (decoration) {
447
+ commands.push({
448
+ type: "resetDecoration",
449
+ value: decoration
450
+ });
451
+ if (decoration === "dim") commands.push({
452
+ type: "resetDecoration",
453
+ value: "bold"
454
+ });
455
+ }
456
+ } else if (codeInt <= 37) commands.push({
457
+ type: "setForegroundColor",
458
+ value: {
459
+ type: "named",
460
+ name: namedColors[codeInt - 30]
461
+ }
462
+ });
463
+ else if (codeInt === 38) {
464
+ const color = parseColor(sequence);
465
+ if (color) commands.push({
466
+ type: "setForegroundColor",
467
+ value: color
468
+ });
469
+ } else if (codeInt === 39) commands.push({ type: "resetForegroundColor" });
470
+ else if (codeInt <= 47) commands.push({
471
+ type: "setBackgroundColor",
472
+ value: {
473
+ type: "named",
474
+ name: namedColors[codeInt - 40]
475
+ }
476
+ });
477
+ else if (codeInt === 48) {
478
+ const color = parseColor(sequence);
479
+ if (color) commands.push({
480
+ type: "setBackgroundColor",
481
+ value: color
482
+ });
483
+ } else if (codeInt === 49) commands.push({ type: "resetBackgroundColor" });
484
+ else if (codeInt === 53) commands.push({
485
+ type: "setDecoration",
486
+ value: "overline"
487
+ });
488
+ else if (codeInt === 55) commands.push({
489
+ type: "resetDecoration",
490
+ value: "overline"
491
+ });
492
+ else if (codeInt >= 90 && codeInt <= 97) commands.push({
493
+ type: "setForegroundColor",
494
+ value: {
495
+ type: "named",
496
+ name: namedColors[codeInt - 90 + 8]
497
+ }
498
+ });
499
+ else if (codeInt >= 100 && codeInt <= 107) commands.push({
500
+ type: "setBackgroundColor",
501
+ value: {
502
+ type: "named",
503
+ name: namedColors[codeInt - 100 + 8]
504
+ }
505
+ });
506
+ }
507
+ return commands;
677
508
  }
678
509
  function createAnsiSequenceParser() {
679
- let foreground = null;
680
- let background = null;
681
- let decorations2 = /* @__PURE__ */ new Set();
682
- return {
683
- parse(value) {
684
- const tokens = [];
685
- let position = 0;
686
- do {
687
- const findResult = findSequence(value, position);
688
- const text = findResult.sequence ? value.substring(position, findResult.startPosition) : value.substring(position);
689
- if (text.length > 0) {
690
- tokens.push({
691
- value: text,
692
- foreground,
693
- background,
694
- decorations: new Set(decorations2)
695
- });
696
- }
697
- if (findResult.sequence) {
698
- const commands = parseSequence(findResult.sequence);
699
- for (const styleToken of commands) {
700
- if (styleToken.type === "resetAll") {
701
- foreground = null;
702
- background = null;
703
- decorations2.clear();
704
- } else if (styleToken.type === "resetForegroundColor") {
705
- foreground = null;
706
- } else if (styleToken.type === "resetBackgroundColor") {
707
- background = null;
708
- } else if (styleToken.type === "resetDecoration") {
709
- decorations2.delete(styleToken.value);
710
- }
711
- }
712
- for (const styleToken of commands) {
713
- if (styleToken.type === "setForegroundColor") {
714
- foreground = styleToken.value;
715
- } else if (styleToken.type === "setBackgroundColor") {
716
- background = styleToken.value;
717
- } else if (styleToken.type === "setDecoration") {
718
- decorations2.add(styleToken.value);
719
- }
720
- }
721
- }
722
- position = findResult.position;
723
- } while (position < value.length);
724
- return tokens;
725
- }
726
- };
510
+ let foreground = null;
511
+ let background = null;
512
+ let decorations2 = /* @__PURE__ */ new Set();
513
+ return { parse(value) {
514
+ const tokens = [];
515
+ let position = 0;
516
+ do {
517
+ const findResult = findSequence(value, position);
518
+ const text = findResult.sequence ? value.substring(position, findResult.startPosition) : value.substring(position);
519
+ if (text.length > 0) tokens.push({
520
+ value: text,
521
+ foreground,
522
+ background,
523
+ decorations: new Set(decorations2)
524
+ });
525
+ if (findResult.sequence) {
526
+ const commands = parseSequence(findResult.sequence);
527
+ for (const styleToken of commands) if (styleToken.type === "resetAll") {
528
+ foreground = null;
529
+ background = null;
530
+ decorations2.clear();
531
+ } else if (styleToken.type === "resetForegroundColor") foreground = null;
532
+ else if (styleToken.type === "resetBackgroundColor") background = null;
533
+ else if (styleToken.type === "resetDecoration") decorations2.delete(styleToken.value);
534
+ for (const styleToken of commands) if (styleToken.type === "setForegroundColor") foreground = styleToken.value;
535
+ else if (styleToken.type === "setBackgroundColor") background = styleToken.value;
536
+ else if (styleToken.type === "setDecoration") decorations2.add(styleToken.value);
537
+ }
538
+ position = findResult.position;
539
+ } while (position < value.length);
540
+ return tokens;
541
+ } };
727
542
  }
728
-
729
- // src/palette.ts
730
543
  var defaultNamedColorsMap = {
731
- black: "#000000",
732
- red: "#bb0000",
733
- green: "#00bb00",
734
- yellow: "#bbbb00",
735
- blue: "#0000bb",
736
- magenta: "#ff00ff",
737
- cyan: "#00bbbb",
738
- white: "#eeeeee",
739
- brightBlack: "#555555",
740
- brightRed: "#ff5555",
741
- brightGreen: "#00ff00",
742
- brightYellow: "#ffff55",
743
- brightBlue: "#5555ff",
744
- brightMagenta: "#ff55ff",
745
- brightCyan: "#55ffff",
746
- brightWhite: "#ffffff"
544
+ black: "#000000",
545
+ red: "#bb0000",
546
+ green: "#00bb00",
547
+ yellow: "#bbbb00",
548
+ blue: "#0000bb",
549
+ magenta: "#ff00ff",
550
+ cyan: "#00bbbb",
551
+ white: "#eeeeee",
552
+ brightBlack: "#555555",
553
+ brightRed: "#ff5555",
554
+ brightGreen: "#00ff00",
555
+ brightYellow: "#ffff55",
556
+ brightBlue: "#5555ff",
557
+ brightMagenta: "#ff55ff",
558
+ brightCyan: "#55ffff",
559
+ brightWhite: "#ffffff"
747
560
  };
748
561
  function createColorPalette(namedColorsMap = defaultNamedColorsMap) {
749
- function namedColor(name) {
750
- return namedColorsMap[name];
751
- }
752
- function rgbColor(rgb) {
753
- return `#${rgb.map((x) => Math.max(0, Math.min(x, 255)).toString(16).padStart(2, "0")).join("")}`;
754
- }
755
- let colorTable;
756
- function getColorTable() {
757
- if (colorTable) {
758
- return colorTable;
759
- }
760
- colorTable = [];
761
- for (let i = 0; i < namedColors.length; i++) {
762
- colorTable.push(namedColor(namedColors[i]));
763
- }
764
- let levels = [0, 95, 135, 175, 215, 255];
765
- for (let r = 0; r < 6; r++) {
766
- for (let g = 0; g < 6; g++) {
767
- for (let b = 0; b < 6; b++) {
768
- colorTable.push(rgbColor([levels[r], levels[g], levels[b]]));
769
- }
770
- }
771
- }
772
- let level = 8;
773
- for (let i = 0; i < 24; i++, level += 10) {
774
- colorTable.push(rgbColor([level, level, level]));
775
- }
776
- return colorTable;
777
- }
778
- function tableColor(index) {
779
- return getColorTable()[index];
780
- }
781
- function value(color) {
782
- switch (color.type) {
783
- case "named":
784
- return namedColor(color.name);
785
- case "rgb":
786
- return rgbColor(color.rgb);
787
- case "table":
788
- return tableColor(color.index);
789
- }
790
- }
791
- return {
792
- value
793
- };
562
+ function namedColor(name) {
563
+ return namedColorsMap[name];
564
+ }
565
+ function rgbColor(rgb) {
566
+ return `#${rgb.map((x) => Math.max(0, Math.min(x, 255)).toString(16).padStart(2, "0")).join("")}`;
567
+ }
568
+ let colorTable;
569
+ function getColorTable() {
570
+ if (colorTable) return colorTable;
571
+ colorTable = [];
572
+ for (let i = 0; i < namedColors.length; i++) colorTable.push(namedColor(namedColors[i]));
573
+ let levels = [
574
+ 0,
575
+ 95,
576
+ 135,
577
+ 175,
578
+ 215,
579
+ 255
580
+ ];
581
+ for (let r = 0; r < 6; r++) for (let g = 0; g < 6; g++) for (let b = 0; b < 6; b++) colorTable.push(rgbColor([
582
+ levels[r],
583
+ levels[g],
584
+ levels[b]
585
+ ]));
586
+ let level = 8;
587
+ for (let i = 0; i < 24; i++, level += 10) colorTable.push(rgbColor([
588
+ level,
589
+ level,
590
+ level
591
+ ]));
592
+ return colorTable;
593
+ }
594
+ function tableColor(index) {
595
+ return getColorTable()[index];
596
+ }
597
+ function value(color) {
598
+ switch (color.type) {
599
+ case "named": return namedColor(color.name);
600
+ case "rgb": return rgbColor(color.rgb);
601
+ case "table": return tableColor(color.index);
602
+ }
603
+ }
604
+ return { value };
794
605
  }
795
606
 
607
+ //#endregion
608
+ //#region src/highlight/code-to-tokens-ansi.ts
609
+ /**
610
+ * Default ANSI palette (VSCode compatible fallbacks)
611
+ * Used when the theme does not define terminal.ansi* colors.
612
+ */
796
613
  const defaultAnsiColors = {
797
- black: "#000000",
798
- red: "#cd3131",
799
- green: "#0DBC79",
800
- yellow: "#E5E510",
801
- blue: "#2472C8",
802
- magenta: "#BC3FBC",
803
- cyan: "#11A8CD",
804
- white: "#E5E5E5",
805
- brightBlack: "#666666",
806
- brightRed: "#F14C4C",
807
- brightGreen: "#23D18B",
808
- brightYellow: "#F5F543",
809
- brightBlue: "#3B8EEA",
810
- brightMagenta: "#D670D6",
811
- brightCyan: "#29B8DB",
812
- brightWhite: "#FFFFFF"
614
+ black: "#000000",
615
+ red: "#cd3131",
616
+ green: "#0DBC79",
617
+ yellow: "#E5E510",
618
+ blue: "#2472C8",
619
+ magenta: "#BC3FBC",
620
+ cyan: "#11A8CD",
621
+ white: "#E5E5E5",
622
+ brightBlack: "#666666",
623
+ brightRed: "#F14C4C",
624
+ brightGreen: "#23D18B",
625
+ brightYellow: "#F5F543",
626
+ brightBlue: "#3B8EEA",
627
+ brightMagenta: "#D670D6",
628
+ brightCyan: "#29B8DB",
629
+ brightWhite: "#FFFFFF"
813
630
  };
814
631
  function tokenizeAnsiWithTheme(theme, fileContents, options) {
815
- const colorReplacements = resolveColorReplacements(theme, options);
816
- const lines = splitLines(fileContents);
817
- const ansiPalette = Object.fromEntries(
818
- namedColors.map((name) => {
819
- const key = `terminal.ansi${name[0].toUpperCase()}${name.substring(1)}`;
820
- const themeColor = theme.colors?.[key];
821
- return [name, themeColor || defaultAnsiColors[name]];
822
- })
823
- );
824
- const colorPalette = createColorPalette(ansiPalette);
825
- const parser = createAnsiSequenceParser();
826
- return lines.map(
827
- (line) => parser.parse(line[0]).map((token) => {
828
- let color;
829
- let bgColor;
830
- if (token.decorations.has("reverse")) {
831
- color = token.background ? colorPalette.value(token.background) : theme.bg;
832
- bgColor = token.foreground ? colorPalette.value(token.foreground) : theme.fg;
833
- } else {
834
- color = token.foreground ? colorPalette.value(token.foreground) : theme.fg;
835
- bgColor = token.background ? colorPalette.value(token.background) : void 0;
836
- }
837
- color = applyColorReplacements(color, colorReplacements);
838
- bgColor = applyColorReplacements(bgColor, colorReplacements);
839
- if (token.decorations.has("dim"))
840
- color = dimColor(color);
841
- let fontStyle = FontStyle.None;
842
- if (token.decorations.has("bold"))
843
- fontStyle |= FontStyle.Bold;
844
- if (token.decorations.has("italic"))
845
- fontStyle |= FontStyle.Italic;
846
- if (token.decorations.has("underline"))
847
- fontStyle |= FontStyle.Underline;
848
- if (token.decorations.has("strikethrough"))
849
- fontStyle |= FontStyle.Strikethrough;
850
- return {
851
- content: token.value,
852
- offset: line[1],
853
- // TODO: more accurate offset? might need to fork ansi-sequence-parser
854
- color,
855
- bgColor,
856
- fontStyle
857
- };
858
- })
859
- );
860
- }
632
+ const colorReplacements = resolveColorReplacements(theme, options);
633
+ const lines = splitLines(fileContents);
634
+ const colorPalette = createColorPalette(Object.fromEntries(namedColors.map((name) => {
635
+ const key = `terminal.ansi${name[0].toUpperCase()}${name.substring(1)}`;
636
+ return [name, theme.colors?.[key] || defaultAnsiColors[name]];
637
+ })));
638
+ const parser = createAnsiSequenceParser();
639
+ return lines.map((line) => parser.parse(line[0]).map((token) => {
640
+ let color;
641
+ let bgColor;
642
+ if (token.decorations.has("reverse")) {
643
+ color = token.background ? colorPalette.value(token.background) : theme.bg;
644
+ bgColor = token.foreground ? colorPalette.value(token.foreground) : theme.fg;
645
+ } else {
646
+ color = token.foreground ? colorPalette.value(token.foreground) : theme.fg;
647
+ bgColor = token.background ? colorPalette.value(token.background) : void 0;
648
+ }
649
+ color = applyColorReplacements(color, colorReplacements);
650
+ bgColor = applyColorReplacements(bgColor, colorReplacements);
651
+ if (token.decorations.has("dim")) color = dimColor(color);
652
+ let fontStyle = FontStyle.None;
653
+ if (token.decorations.has("bold")) fontStyle |= FontStyle.Bold;
654
+ if (token.decorations.has("italic")) fontStyle |= FontStyle.Italic;
655
+ if (token.decorations.has("underline")) fontStyle |= FontStyle.Underline;
656
+ if (token.decorations.has("strikethrough")) fontStyle |= FontStyle.Strikethrough;
657
+ return {
658
+ content: token.value,
659
+ offset: line[1],
660
+ color,
661
+ bgColor,
662
+ fontStyle
663
+ };
664
+ }));
665
+ }
666
+ /**
667
+ * Adds 50% alpha to a hex color string or the "-dim" postfix to a CSS variable
668
+ */
861
669
  function dimColor(color) {
862
- const hexMatch = color.match(/#([0-9a-f]{3,8})/i);
863
- if (hexMatch) {
864
- const hex = hexMatch[1];
865
- if (hex.length === 8) {
866
- const alpha = Math.round(Number.parseInt(hex.slice(6, 8), 16) / 2).toString(16).padStart(2, "0");
867
- return `#${hex.slice(0, 6)}${alpha}`;
868
- } else if (hex.length === 6) {
869
- return `#${hex}80`;
870
- } else if (hex.length === 4) {
871
- const r = hex[0];
872
- const g = hex[1];
873
- const b = hex[2];
874
- const a = hex[3];
875
- const alpha = Math.round(Number.parseInt(`${a}${a}`, 16) / 2).toString(16).padStart(2, "0");
876
- return `#${r}${r}${g}${g}${b}${b}${alpha}`;
877
- } else if (hex.length === 3) {
878
- const r = hex[0];
879
- const g = hex[1];
880
- const b = hex[2];
881
- return `#${r}${r}${g}${g}${b}${b}80`;
882
- }
883
- }
884
- const cssVarMatch = color.match(/var\((--[\w-]+-ansi-[\w-]+)\)/);
885
- if (cssVarMatch)
886
- return `var(${cssVarMatch[1]}-dim)`;
887
- return color;
670
+ const hexMatch = color.match(/#([0-9a-f]{3,8})/i);
671
+ if (hexMatch) {
672
+ const hex = hexMatch[1];
673
+ if (hex.length === 8) {
674
+ const alpha = Math.round(Number.parseInt(hex.slice(6, 8), 16) / 2).toString(16).padStart(2, "0");
675
+ return `#${hex.slice(0, 6)}${alpha}`;
676
+ } else if (hex.length === 6) return `#${hex}80`;
677
+ else if (hex.length === 4) {
678
+ const r = hex[0];
679
+ const g = hex[1];
680
+ const b = hex[2];
681
+ const a = hex[3];
682
+ return `#${r}${r}${g}${g}${b}${b}${Math.round(Number.parseInt(`${a}${a}`, 16) / 2).toString(16).padStart(2, "0")}`;
683
+ } else if (hex.length === 3) {
684
+ const r = hex[0];
685
+ const g = hex[1];
686
+ const b = hex[2];
687
+ return `#${r}${r}${g}${g}${b}${b}80`;
688
+ }
689
+ }
690
+ const cssVarMatch = color.match(/var\((--[\w-]+-ansi-[\w-]+)\)/);
691
+ if (cssVarMatch) return `var(${cssVarMatch[1]}-dim)`;
692
+ return color;
888
693
  }
889
694
 
890
- function codeToTokensBase(internal, code, options = {}) {
891
- const {
892
- theme: themeName = internal.getLoadedThemes()[0]
893
- } = options;
894
- const lang = internal.resolveLangAlias(options.lang || "text");
895
- if (isPlainLang(lang) || isNoneTheme(themeName))
896
- return splitLines(code).map((line) => [{ content: line[0], offset: line[1] }]);
897
- const { theme, colorMap } = internal.setTheme(themeName);
898
- if (lang === "ansi")
899
- return tokenizeAnsiWithTheme(theme, code, options);
900
- const _grammar = internal.getLanguage(options.lang || "text");
901
- if (options.grammarState) {
902
- if (options.grammarState.lang !== _grammar.name) {
903
- throw new ShikiError$1(`Grammar state language "${options.grammarState.lang}" does not match highlight language "${_grammar.name}"`);
904
- }
905
- if (!options.grammarState.themes.includes(theme.name)) {
906
- throw new ShikiError$1(`Grammar state themes "${options.grammarState.themes}" do not contain highlight theme "${theme.name}"`);
907
- }
908
- }
909
- return tokenizeWithTheme(code, _grammar, theme, colorMap, options);
910
- }
911
- function getLastGrammarState(...args) {
912
- if (args.length === 2) {
913
- return getLastGrammarStateFromMap(args[1]);
914
- }
915
- const [internal, code, options = {}] = args;
916
- const {
917
- lang = "text",
918
- theme: themeName = internal.getLoadedThemes()[0]
919
- } = options;
920
- if (isPlainLang(lang) || isNoneTheme(themeName))
921
- throw new ShikiError$1("Plain language does not have grammar state");
922
- if (lang === "ansi")
923
- throw new ShikiError$1("ANSI language does not have grammar state");
924
- const { theme, colorMap } = internal.setTheme(themeName);
925
- const _grammar = internal.getLanguage(lang);
926
- return new GrammarState(
927
- _tokenizeWithTheme(code, _grammar, theme, colorMap, options).stateStack,
928
- _grammar.name,
929
- theme.name
930
- );
931
- }
932
- function tokenizeWithTheme(code, grammar, theme, colorMap, options) {
933
- const result = _tokenizeWithTheme(code, grammar, theme, colorMap, options);
934
- const grammarState = new GrammarState(
935
- result.stateStack,
936
- grammar.name,
937
- theme.name
938
- );
939
- setLastGrammarStateToMap(result.tokens, grammarState);
940
- return result.tokens;
941
- }
942
- function _tokenizeWithTheme(code, grammar, theme, colorMap, options) {
943
- const colorReplacements = resolveColorReplacements(theme, options);
944
- const {
945
- tokenizeMaxLineLength = 0,
946
- tokenizeTimeLimit = 500
947
- } = options;
948
- const lines = splitLines(code);
949
- let stateStack = options.grammarState ? getGrammarStack(options.grammarState, theme.name) ?? INITIAL : options.grammarContextCode != null ? _tokenizeWithTheme(
950
- options.grammarContextCode,
951
- grammar,
952
- theme,
953
- colorMap,
954
- {
955
- ...options,
956
- grammarState: void 0,
957
- grammarContextCode: void 0
958
- }
959
- ).stateStack : INITIAL;
960
- let actual = [];
961
- const final = [];
962
- for (let i = 0, len = lines.length; i < len; i++) {
963
- const [line, lineOffset] = lines[i];
964
- if (line === "") {
965
- actual = [];
966
- final.push([]);
967
- continue;
968
- }
969
- if (tokenizeMaxLineLength > 0 && line.length >= tokenizeMaxLineLength) {
970
- actual = [];
971
- final.push([{
972
- content: line,
973
- offset: lineOffset,
974
- color: "",
975
- fontStyle: 0
976
- }]);
977
- continue;
978
- }
979
- let resultWithScopes;
980
- let tokensWithScopes;
981
- let tokensWithScopesIndex;
982
- if (options.includeExplanation) {
983
- resultWithScopes = grammar.tokenizeLine(line, stateStack, tokenizeTimeLimit);
984
- tokensWithScopes = resultWithScopes.tokens;
985
- tokensWithScopesIndex = 0;
986
- }
987
- const result = grammar.tokenizeLine2(line, stateStack, tokenizeTimeLimit);
988
- const tokensLength = result.tokens.length / 2;
989
- for (let j = 0; j < tokensLength; j++) {
990
- const startIndex = result.tokens[2 * j];
991
- const nextStartIndex = j + 1 < tokensLength ? result.tokens[2 * j + 2] : line.length;
992
- if (startIndex === nextStartIndex)
993
- continue;
994
- const metadata = result.tokens[2 * j + 1];
995
- const color = applyColorReplacements(
996
- colorMap[EncodedTokenMetadata.getForeground(metadata)],
997
- colorReplacements
998
- );
999
- const fontStyle = EncodedTokenMetadata.getFontStyle(metadata);
1000
- const token = {
1001
- content: line.substring(startIndex, nextStartIndex),
1002
- offset: lineOffset + startIndex,
1003
- color,
1004
- fontStyle
1005
- };
1006
- if (options.includeExplanation) {
1007
- const themeSettingsSelectors = [];
1008
- if (options.includeExplanation !== "scopeName") {
1009
- for (const setting of theme.settings) {
1010
- let selectors;
1011
- switch (typeof setting.scope) {
1012
- case "string":
1013
- selectors = setting.scope.split(/,/).map((scope) => scope.trim());
1014
- break;
1015
- case "object":
1016
- selectors = setting.scope;
1017
- break;
1018
- default:
1019
- continue;
1020
- }
1021
- themeSettingsSelectors.push({
1022
- settings: setting,
1023
- selectors: selectors.map((selector) => selector.split(/ /))
1024
- });
1025
- }
1026
- }
1027
- token.explanation = [];
1028
- let offset = 0;
1029
- while (startIndex + offset < nextStartIndex) {
1030
- const tokenWithScopes = tokensWithScopes[tokensWithScopesIndex];
1031
- const tokenWithScopesText = line.substring(
1032
- tokenWithScopes.startIndex,
1033
- tokenWithScopes.endIndex
1034
- );
1035
- offset += tokenWithScopesText.length;
1036
- token.explanation.push({
1037
- content: tokenWithScopesText,
1038
- scopes: options.includeExplanation === "scopeName" ? explainThemeScopesNameOnly(
1039
- tokenWithScopes.scopes
1040
- ) : explainThemeScopesFull(
1041
- themeSettingsSelectors,
1042
- tokenWithScopes.scopes
1043
- )
1044
- });
1045
- tokensWithScopesIndex += 1;
1046
- }
1047
- }
1048
- actual.push(token);
1049
- }
1050
- final.push(actual);
1051
- actual = [];
1052
- stateStack = result.ruleStack;
1053
- }
1054
- return {
1055
- tokens: final,
1056
- stateStack
1057
- };
1058
- }
1059
- function explainThemeScopesNameOnly(scopes) {
1060
- return scopes.map((scope) => ({ scopeName: scope }));
1061
- }
1062
- function explainThemeScopesFull(themeSelectors, scopes) {
1063
- const result = [];
1064
- for (let i = 0, len = scopes.length; i < len; i++) {
1065
- const scope = scopes[i];
1066
- result[i] = {
1067
- scopeName: scope,
1068
- themeMatches: explainThemeScope(themeSelectors, scope, scopes.slice(0, i))
1069
- };
1070
- }
1071
- return result;
1072
- }
1073
- function matchesOne(selector, scope) {
1074
- return selector === scope || scope.substring(0, selector.length) === selector && scope[selector.length] === ".";
1075
- }
1076
- function matches(selectors, scope, parentScopes) {
1077
- if (!matchesOne(selectors[selectors.length - 1], scope))
1078
- return false;
1079
- let selectorParentIndex = selectors.length - 2;
1080
- let parentIndex = parentScopes.length - 1;
1081
- while (selectorParentIndex >= 0 && parentIndex >= 0) {
1082
- if (matchesOne(selectors[selectorParentIndex], parentScopes[parentIndex]))
1083
- selectorParentIndex -= 1;
1084
- parentIndex -= 1;
1085
- }
1086
- if (selectorParentIndex === -1)
1087
- return true;
1088
- return false;
1089
- }
1090
- function explainThemeScope(themeSettingsSelectors, scope, parentScopes) {
1091
- const result = [];
1092
- for (const { selectors, settings } of themeSettingsSelectors) {
1093
- for (const selectorPieces of selectors) {
1094
- if (matches(selectorPieces, scope, parentScopes)) {
1095
- result.push(settings);
1096
- break;
1097
- }
1098
- }
1099
- }
1100
- return result;
695
+ //#endregion
696
+ //#region src/highlight/code-to-tokens-base.ts
697
+ /**
698
+ * Code to tokens, with a simple theme.
699
+ * This wraps the tokenizer's implementation to add ANSI support.
700
+ */
701
+ function codeToTokensBase(primitive, code, options = {}) {
702
+ const lang = primitive.resolveLangAlias(options.lang || "text");
703
+ const { theme: themeName = primitive.getLoadedThemes()[0] } = options;
704
+ if (!isPlainLang(lang) && !isNoneTheme(themeName) && lang === "ansi") {
705
+ const { theme } = primitive.setTheme(themeName);
706
+ return tokenizeAnsiWithTheme(theme, code, options);
707
+ }
708
+ return codeToTokensBase$1(primitive, code, options);
1101
709
  }
1102
710
 
1103
- function codeToTokensWithThemes(internal, code, options) {
1104
- const themes = Object.entries(options.themes).filter((i) => i[1]).map((i) => ({ color: i[0], theme: i[1] }));
1105
- const themedTokens = themes.map((t) => {
1106
- const tokens2 = codeToTokensBase(internal, code, {
1107
- ...options,
1108
- theme: t.theme
1109
- });
1110
- const state = getLastGrammarStateFromMap(tokens2);
1111
- const theme = typeof t.theme === "string" ? t.theme : t.theme.name;
1112
- return {
1113
- tokens: tokens2,
1114
- state,
1115
- theme
1116
- };
1117
- });
1118
- const tokens = syncThemesTokenization(
1119
- ...themedTokens.map((i) => i.tokens)
1120
- );
1121
- const mergedTokens = tokens[0].map(
1122
- (line, lineIdx) => line.map((_token, tokenIdx) => {
1123
- const mergedToken = {
1124
- content: _token.content,
1125
- variants: {},
1126
- offset: _token.offset
1127
- };
1128
- if ("includeExplanation" in options && options.includeExplanation) {
1129
- mergedToken.explanation = _token.explanation;
1130
- }
1131
- tokens.forEach((t, themeIdx) => {
1132
- const {
1133
- content: _,
1134
- explanation: __,
1135
- offset: ___,
1136
- ...styles
1137
- } = t[lineIdx][tokenIdx];
1138
- mergedToken.variants[themes[themeIdx].color] = styles;
1139
- });
1140
- return mergedToken;
1141
- })
1142
- );
1143
- const mergedGrammarState = themedTokens[0].state ? new GrammarState(
1144
- Object.fromEntries(themedTokens.map((s) => [s.theme, s.state?.getInternalStack(s.theme)])),
1145
- themedTokens[0].state.lang
1146
- ) : void 0;
1147
- if (mergedGrammarState)
1148
- setLastGrammarStateToMap(mergedTokens, mergedGrammarState);
1149
- return mergedTokens;
1150
- }
1151
- function syncThemesTokenization(...themes) {
1152
- const outThemes = themes.map(() => []);
1153
- const count = themes.length;
1154
- for (let i = 0; i < themes[0].length; i++) {
1155
- const lines = themes.map((t) => t[i]);
1156
- const outLines = outThemes.map(() => []);
1157
- outThemes.forEach((t, i2) => t.push(outLines[i2]));
1158
- const indexes = lines.map(() => 0);
1159
- const current = lines.map((l) => l[0]);
1160
- while (current.every((t) => t)) {
1161
- const minLength = Math.min(...current.map((t) => t.content.length));
1162
- for (let n = 0; n < count; n++) {
1163
- const token = current[n];
1164
- if (token.content.length === minLength) {
1165
- outLines[n].push(token);
1166
- indexes[n] += 1;
1167
- current[n] = lines[n][indexes[n]];
1168
- } else {
1169
- outLines[n].push({
1170
- ...token,
1171
- content: token.content.slice(0, minLength)
1172
- });
1173
- current[n] = {
1174
- ...token,
1175
- content: token.content.slice(minLength),
1176
- offset: token.offset + minLength
1177
- };
1178
- }
1179
- }
1180
- }
1181
- }
1182
- return outThemes;
1183
- }
1184
-
1185
- function codeToTokens(internal, code, options) {
1186
- let bg;
1187
- let fg;
1188
- let tokens;
1189
- let themeName;
1190
- let rootStyle;
1191
- let grammarState;
1192
- if ("themes" in options) {
1193
- const {
1194
- defaultColor = "light",
1195
- cssVariablePrefix = "--shiki-",
1196
- colorsRendering = "css-vars"
1197
- } = options;
1198
- const themes = Object.entries(options.themes).filter((i) => i[1]).map((i) => ({ color: i[0], theme: i[1] })).sort((a, b) => a.color === defaultColor ? -1 : b.color === defaultColor ? 1 : 0);
1199
- if (themes.length === 0)
1200
- throw new ShikiError$1("`themes` option must not be empty");
1201
- const themeTokens = codeToTokensWithThemes(
1202
- internal,
1203
- code,
1204
- options
1205
- );
1206
- grammarState = getLastGrammarStateFromMap(themeTokens);
1207
- if (defaultColor && DEFAULT_COLOR_LIGHT_DARK !== defaultColor && !themes.find((t) => t.color === defaultColor))
1208
- throw new ShikiError$1(`\`themes\` option must contain the defaultColor key \`${defaultColor}\``);
1209
- const themeRegs = themes.map((t) => internal.getTheme(t.theme));
1210
- const themesOrder = themes.map((t) => t.color);
1211
- tokens = themeTokens.map((line) => line.map((token) => flatTokenVariants(token, themesOrder, cssVariablePrefix, defaultColor, colorsRendering)));
1212
- if (grammarState)
1213
- setLastGrammarStateToMap(tokens, grammarState);
1214
- const themeColorReplacements = themes.map((t) => resolveColorReplacements(t.theme, options));
1215
- fg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "fg", colorsRendering);
1216
- bg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "bg", colorsRendering);
1217
- themeName = `shiki-themes ${themeRegs.map((t) => t.name).join(" ")}`;
1218
- rootStyle = defaultColor ? void 0 : [fg, bg].join(";");
1219
- } else if ("theme" in options) {
1220
- const colorReplacements = resolveColorReplacements(options.theme, options);
1221
- tokens = codeToTokensBase(
1222
- internal,
1223
- code,
1224
- options
1225
- );
1226
- const _theme = internal.getTheme(options.theme);
1227
- bg = applyColorReplacements(_theme.bg, colorReplacements);
1228
- fg = applyColorReplacements(_theme.fg, colorReplacements);
1229
- themeName = _theme.name;
1230
- grammarState = getLastGrammarStateFromMap(tokens);
1231
- } else {
1232
- throw new ShikiError$1("Invalid options, either `theme` or `themes` must be provided");
1233
- }
1234
- return {
1235
- tokens,
1236
- fg,
1237
- bg,
1238
- themeName,
1239
- rootStyle,
1240
- grammarState
1241
- };
711
+ //#endregion
712
+ //#region src/highlight/code-to-tokens.ts
713
+ /**
714
+ * High-level code-to-tokens API.
715
+ *
716
+ * It will use `codeToTokensWithThemes` or `codeToTokensBase` based on the options.
717
+ */
718
+ function codeToTokens(primitive, code, options) {
719
+ let bg;
720
+ let fg;
721
+ let tokens;
722
+ let themeName;
723
+ let rootStyle;
724
+ let grammarState;
725
+ if ("themes" in options) {
726
+ const { defaultColor = "light", cssVariablePrefix = "--shiki-", colorsRendering = "css-vars" } = options;
727
+ const themes = Object.entries(options.themes).filter((i) => i[1]).map((i) => ({
728
+ color: i[0],
729
+ theme: i[1]
730
+ })).sort((a, b) => a.color === defaultColor ? -1 : b.color === defaultColor ? 1 : 0);
731
+ if (themes.length === 0) throw new ShikiError$1("`themes` option must not be empty");
732
+ const themeTokens = codeToTokensWithThemes$1(primitive, code, options);
733
+ grammarState = getLastGrammarStateFromMap(themeTokens);
734
+ if (defaultColor && DEFAULT_COLOR_LIGHT_DARK !== defaultColor && !themes.find((t) => t.color === defaultColor)) throw new ShikiError$1(`\`themes\` option must contain the defaultColor key \`${defaultColor}\``);
735
+ const themeRegs = themes.map((t) => primitive.getTheme(t.theme));
736
+ const themesOrder = themes.map((t) => t.color);
737
+ tokens = themeTokens.map((line) => line.map((token) => flatTokenVariants(token, themesOrder, cssVariablePrefix, defaultColor, colorsRendering)));
738
+ if (grammarState) setLastGrammarStateToMap(tokens, grammarState);
739
+ const themeColorReplacements = themes.map((t) => resolveColorReplacements(t.theme, options));
740
+ fg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "fg", colorsRendering);
741
+ bg = mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, "bg", colorsRendering);
742
+ themeName = `shiki-themes ${themeRegs.map((t) => t.name).join(" ")}`;
743
+ rootStyle = defaultColor ? void 0 : [fg, bg].join(";");
744
+ } else if ("theme" in options) {
745
+ const colorReplacements = resolveColorReplacements(options.theme, options);
746
+ tokens = codeToTokensBase(primitive, code, options);
747
+ const _theme = primitive.getTheme(options.theme);
748
+ bg = applyColorReplacements(_theme.bg, colorReplacements);
749
+ fg = applyColorReplacements(_theme.fg, colorReplacements);
750
+ themeName = _theme.name;
751
+ grammarState = getLastGrammarStateFromMap(tokens);
752
+ } else throw new ShikiError$1("Invalid options, either `theme` or `themes` must be provided");
753
+ return {
754
+ tokens,
755
+ fg,
756
+ bg,
757
+ themeName,
758
+ rootStyle,
759
+ grammarState
760
+ };
1242
761
  }
1243
762
  function mapThemeColors(themes, themeRegs, themeColorReplacements, cssVariablePrefix, defaultColor, property, colorsRendering) {
1244
- return themes.map((t, idx) => {
1245
- const value = applyColorReplacements(themeRegs[idx][property], themeColorReplacements[idx]) || "inherit";
1246
- const cssVar = `${cssVariablePrefix + t.color}${property === "bg" ? "-bg" : ""}:${value}`;
1247
- if (idx === 0 && defaultColor) {
1248
- if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && themes.length > 1) {
1249
- const lightIndex = themes.findIndex((t2) => t2.color === "light");
1250
- const darkIndex = themes.findIndex((t2) => t2.color === "dark");
1251
- if (lightIndex === -1 || darkIndex === -1)
1252
- throw new ShikiError$1('When using `defaultColor: "light-dark()"`, you must provide both `light` and `dark` themes');
1253
- const lightValue = applyColorReplacements(themeRegs[lightIndex][property], themeColorReplacements[lightIndex]) || "inherit";
1254
- const darkValue = applyColorReplacements(themeRegs[darkIndex][property], themeColorReplacements[darkIndex]) || "inherit";
1255
- return `light-dark(${lightValue}, ${darkValue});${cssVar}`;
1256
- }
1257
- return value;
1258
- }
1259
- if (colorsRendering === "css-vars") {
1260
- return cssVar;
1261
- }
1262
- return null;
1263
- }).filter((i) => !!i).join(";");
763
+ return themes.map((t, idx) => {
764
+ const value = applyColorReplacements(themeRegs[idx][property], themeColorReplacements[idx]) || "inherit";
765
+ const cssVar = `${cssVariablePrefix + t.color}${property === "bg" ? "-bg" : ""}:${value}`;
766
+ if (idx === 0 && defaultColor) {
767
+ if (defaultColor === DEFAULT_COLOR_LIGHT_DARK && themes.length > 1) {
768
+ const lightIndex = themes.findIndex((t) => t.color === "light");
769
+ const darkIndex = themes.findIndex((t) => t.color === "dark");
770
+ if (lightIndex === -1 || darkIndex === -1) throw new ShikiError$1("When using `defaultColor: \"light-dark()\"`, you must provide both `light` and `dark` themes");
771
+ return `light-dark(${applyColorReplacements(themeRegs[lightIndex][property], themeColorReplacements[lightIndex]) || "inherit"}, ${applyColorReplacements(themeRegs[darkIndex][property], themeColorReplacements[darkIndex]) || "inherit"});${cssVar}`;
772
+ }
773
+ return value;
774
+ }
775
+ if (colorsRendering === "css-vars") return cssVar;
776
+ return null;
777
+ }).filter((i) => !!i).join(";");
1264
778
  }
1265
779
 
1266
- function codeToHast(internal, code, options, transformerContext = {
1267
- meta: {},
1268
- options,
1269
- codeToHast: (_code, _options) => codeToHast(internal, _code, _options),
1270
- codeToTokens: (_code, _options) => codeToTokens(internal, _code, _options)
780
+ //#endregion
781
+ //#region src/highlight/code-to-hast.ts
782
+ function codeToHast(primitive, code, options, transformerContext = {
783
+ meta: {},
784
+ options,
785
+ codeToHast: (_code, _options) => codeToHast(primitive, _code, _options),
786
+ codeToTokens: (_code, _options) => codeToTokens(primitive, _code, _options)
1271
787
  }) {
1272
- let input = code;
1273
- for (const transformer of getTransformers(options))
1274
- input = transformer.preprocess?.call(transformerContext, input, options) || input;
1275
- let {
1276
- tokens,
1277
- fg,
1278
- bg,
1279
- themeName,
1280
- rootStyle,
1281
- grammarState
1282
- } = codeToTokens(internal, input, options);
1283
- const {
1284
- mergeWhitespaces = true,
1285
- mergeSameStyleTokens = false
1286
- } = options;
1287
- if (mergeWhitespaces === true)
1288
- tokens = mergeWhitespaceTokens(tokens);
1289
- else if (mergeWhitespaces === "never")
1290
- tokens = splitWhitespaceTokens(tokens);
1291
- if (mergeSameStyleTokens) {
1292
- tokens = mergeAdjacentStyledTokens(tokens);
1293
- }
1294
- const contextSource = {
1295
- ...transformerContext,
1296
- get source() {
1297
- return input;
1298
- }
1299
- };
1300
- for (const transformer of getTransformers(options))
1301
- tokens = transformer.tokens?.call(contextSource, tokens) || tokens;
1302
- return tokensToHast(
1303
- tokens,
1304
- {
1305
- ...options,
1306
- fg,
1307
- bg,
1308
- themeName,
1309
- rootStyle: options.rootStyle === false ? false : options.rootStyle ?? rootStyle
1310
- },
1311
- contextSource,
1312
- grammarState
1313
- );
788
+ let input = code;
789
+ for (const transformer of getTransformers(options)) input = transformer.preprocess?.call(transformerContext, input, options) || input;
790
+ let { tokens, fg, bg, themeName, rootStyle, grammarState } = codeToTokens(primitive, input, options);
791
+ const { mergeWhitespaces = true, mergeSameStyleTokens = false } = options;
792
+ if (mergeWhitespaces === true) tokens = mergeWhitespaceTokens(tokens);
793
+ else if (mergeWhitespaces === "never") tokens = splitWhitespaceTokens(tokens);
794
+ if (mergeSameStyleTokens) tokens = mergeAdjacentStyledTokens(tokens);
795
+ const contextSource = {
796
+ ...transformerContext,
797
+ get source() {
798
+ return input;
799
+ }
800
+ };
801
+ for (const transformer of getTransformers(options)) tokens = transformer.tokens?.call(contextSource, tokens) || tokens;
802
+ return tokensToHast(tokens, {
803
+ ...options,
804
+ fg,
805
+ bg,
806
+ themeName,
807
+ rootStyle: options.rootStyle === false ? false : options.rootStyle ?? rootStyle
808
+ }, contextSource, grammarState);
1314
809
  }
1315
810
  function tokensToHast(tokens, options, transformerContext, grammarState = getLastGrammarStateFromMap(tokens)) {
1316
- const transformers = getTransformers(options);
1317
- const lines = [];
1318
- const root = {
1319
- type: "root",
1320
- children: []
1321
- };
1322
- const {
1323
- structure = "classic",
1324
- tabindex = "0"
1325
- } = options;
1326
- const properties = {
1327
- class: `shiki ${options.themeName || ""}`
1328
- };
1329
- if (options.rootStyle !== false) {
1330
- if (options.rootStyle != null)
1331
- properties.style = options.rootStyle;
1332
- else
1333
- properties.style = `background-color:${options.bg};color:${options.fg}`;
1334
- }
1335
- if (tabindex !== false && tabindex != null)
1336
- properties.tabindex = tabindex.toString();
1337
- for (const [key, value] of Object.entries(options.meta || {})) {
1338
- if (!key.startsWith("_"))
1339
- properties[key] = value;
1340
- }
1341
- let preNode = {
1342
- type: "element",
1343
- tagName: "pre",
1344
- properties,
1345
- children: [],
1346
- data: options.data
1347
- };
1348
- let codeNode = {
1349
- type: "element",
1350
- tagName: "code",
1351
- properties: {},
1352
- children: lines
1353
- };
1354
- const lineNodes = [];
1355
- const context = {
1356
- ...transformerContext,
1357
- structure,
1358
- addClassToHast,
1359
- get source() {
1360
- return transformerContext.source;
1361
- },
1362
- get tokens() {
1363
- return tokens;
1364
- },
1365
- get options() {
1366
- return options;
1367
- },
1368
- get root() {
1369
- return root;
1370
- },
1371
- get pre() {
1372
- return preNode;
1373
- },
1374
- get code() {
1375
- return codeNode;
1376
- },
1377
- get lines() {
1378
- return lineNodes;
1379
- }
1380
- };
1381
- tokens.forEach((line, idx) => {
1382
- if (idx) {
1383
- if (structure === "inline")
1384
- root.children.push({ type: "element", tagName: "br", properties: {}, children: [] });
1385
- else if (structure === "classic")
1386
- lines.push({ type: "text", value: "\n" });
1387
- }
1388
- let lineNode = {
1389
- type: "element",
1390
- tagName: "span",
1391
- properties: { class: "line" },
1392
- children: []
1393
- };
1394
- let col = 0;
1395
- for (const token of line) {
1396
- let tokenNode = {
1397
- type: "element",
1398
- tagName: "span",
1399
- properties: {
1400
- ...token.htmlAttrs
1401
- },
1402
- children: [{ type: "text", value: token.content }]
1403
- };
1404
- const style = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
1405
- if (style)
1406
- tokenNode.properties.style = style;
1407
- for (const transformer of transformers)
1408
- tokenNode = transformer?.span?.call(context, tokenNode, idx + 1, col, lineNode, token) || tokenNode;
1409
- if (structure === "inline")
1410
- root.children.push(tokenNode);
1411
- else if (structure === "classic")
1412
- lineNode.children.push(tokenNode);
1413
- col += token.content.length;
1414
- }
1415
- if (structure === "classic") {
1416
- for (const transformer of transformers)
1417
- lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
1418
- lineNodes.push(lineNode);
1419
- lines.push(lineNode);
1420
- } else if (structure === "inline") {
1421
- lineNodes.push(lineNode);
1422
- }
1423
- });
1424
- if (structure === "classic") {
1425
- for (const transformer of transformers)
1426
- codeNode = transformer?.code?.call(context, codeNode) || codeNode;
1427
- preNode.children.push(codeNode);
1428
- for (const transformer of transformers)
1429
- preNode = transformer?.pre?.call(context, preNode) || preNode;
1430
- root.children.push(preNode);
1431
- } else if (structure === "inline") {
1432
- const syntheticLines = [];
1433
- let currentLine = {
1434
- type: "element",
1435
- tagName: "span",
1436
- properties: { class: "line" },
1437
- children: []
1438
- };
1439
- for (const child of root.children) {
1440
- if (child.type === "element" && child.tagName === "br") {
1441
- syntheticLines.push(currentLine);
1442
- currentLine = {
1443
- type: "element",
1444
- tagName: "span",
1445
- properties: { class: "line" },
1446
- children: []
1447
- };
1448
- } else if (child.type === "element" || child.type === "text") {
1449
- currentLine.children.push(child);
1450
- }
1451
- }
1452
- syntheticLines.push(currentLine);
1453
- const syntheticCode = {
1454
- type: "element",
1455
- tagName: "code",
1456
- properties: {},
1457
- children: syntheticLines
1458
- };
1459
- let transformedCode = syntheticCode;
1460
- for (const transformer of transformers)
1461
- transformedCode = transformer?.code?.call(context, transformedCode) || transformedCode;
1462
- root.children = [];
1463
- for (let i = 0; i < transformedCode.children.length; i++) {
1464
- if (i > 0)
1465
- root.children.push({ type: "element", tagName: "br", properties: {}, children: [] });
1466
- const line = transformedCode.children[i];
1467
- if (line.type === "element")
1468
- root.children.push(...line.children);
1469
- }
1470
- }
1471
- let result = root;
1472
- for (const transformer of transformers)
1473
- result = transformer?.root?.call(context, result) || result;
1474
- if (grammarState)
1475
- setLastGrammarStateToMap(result, grammarState);
1476
- return result;
811
+ const transformers = getTransformers(options);
812
+ const lines = [];
813
+ const root = {
814
+ type: "root",
815
+ children: []
816
+ };
817
+ const { structure = "classic", tabindex = "0" } = options;
818
+ const properties = { class: `shiki ${options.themeName || ""}` };
819
+ if (options.rootStyle !== false) if (options.rootStyle != null) properties.style = options.rootStyle;
820
+ else properties.style = `background-color:${options.bg};color:${options.fg}`;
821
+ if (tabindex !== false && tabindex != null) properties.tabindex = tabindex.toString();
822
+ for (const [key, value] of Object.entries(options.meta || {})) if (!key.startsWith("_")) properties[key] = value;
823
+ let preNode = {
824
+ type: "element",
825
+ tagName: "pre",
826
+ properties,
827
+ children: [],
828
+ data: options.data
829
+ };
830
+ let codeNode = {
831
+ type: "element",
832
+ tagName: "code",
833
+ properties: {},
834
+ children: lines
835
+ };
836
+ const lineNodes = [];
837
+ const context = {
838
+ ...transformerContext,
839
+ structure,
840
+ addClassToHast,
841
+ get source() {
842
+ return transformerContext.source;
843
+ },
844
+ get tokens() {
845
+ return tokens;
846
+ },
847
+ get options() {
848
+ return options;
849
+ },
850
+ get root() {
851
+ return root;
852
+ },
853
+ get pre() {
854
+ return preNode;
855
+ },
856
+ get code() {
857
+ return codeNode;
858
+ },
859
+ get lines() {
860
+ return lineNodes;
861
+ }
862
+ };
863
+ tokens.forEach((line, idx) => {
864
+ if (idx) {
865
+ if (structure === "inline") root.children.push({
866
+ type: "element",
867
+ tagName: "br",
868
+ properties: {},
869
+ children: []
870
+ });
871
+ else if (structure === "classic") lines.push({
872
+ type: "text",
873
+ value: "\n"
874
+ });
875
+ }
876
+ let lineNode = {
877
+ type: "element",
878
+ tagName: "span",
879
+ properties: { class: "line" },
880
+ children: []
881
+ };
882
+ let col = 0;
883
+ for (const token of line) {
884
+ let tokenNode = {
885
+ type: "element",
886
+ tagName: "span",
887
+ properties: { ...token.htmlAttrs },
888
+ children: [{
889
+ type: "text",
890
+ value: token.content
891
+ }]
892
+ };
893
+ const style = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
894
+ if (style) tokenNode.properties.style = style;
895
+ for (const transformer of transformers) tokenNode = transformer?.span?.call(context, tokenNode, idx + 1, col, lineNode, token) || tokenNode;
896
+ if (structure === "inline") root.children.push(tokenNode);
897
+ else if (structure === "classic") lineNode.children.push(tokenNode);
898
+ col += token.content.length;
899
+ }
900
+ if (structure === "classic") {
901
+ for (const transformer of transformers) lineNode = transformer?.line?.call(context, lineNode, idx + 1) || lineNode;
902
+ lineNodes.push(lineNode);
903
+ lines.push(lineNode);
904
+ } else if (structure === "inline") lineNodes.push(lineNode);
905
+ });
906
+ if (structure === "classic") {
907
+ for (const transformer of transformers) codeNode = transformer?.code?.call(context, codeNode) || codeNode;
908
+ preNode.children.push(codeNode);
909
+ for (const transformer of transformers) preNode = transformer?.pre?.call(context, preNode) || preNode;
910
+ root.children.push(preNode);
911
+ } else if (structure === "inline") {
912
+ const syntheticLines = [];
913
+ let currentLine = {
914
+ type: "element",
915
+ tagName: "span",
916
+ properties: { class: "line" },
917
+ children: []
918
+ };
919
+ for (const child of root.children) if (child.type === "element" && child.tagName === "br") {
920
+ syntheticLines.push(currentLine);
921
+ currentLine = {
922
+ type: "element",
923
+ tagName: "span",
924
+ properties: { class: "line" },
925
+ children: []
926
+ };
927
+ } else if (child.type === "element" || child.type === "text") currentLine.children.push(child);
928
+ syntheticLines.push(currentLine);
929
+ let transformedCode = {
930
+ type: "element",
931
+ tagName: "code",
932
+ properties: {},
933
+ children: syntheticLines
934
+ };
935
+ for (const transformer of transformers) transformedCode = transformer?.code?.call(context, transformedCode) || transformedCode;
936
+ root.children = [];
937
+ for (let i = 0; i < transformedCode.children.length; i++) {
938
+ if (i > 0) root.children.push({
939
+ type: "element",
940
+ tagName: "br",
941
+ properties: {},
942
+ children: []
943
+ });
944
+ const line = transformedCode.children[i];
945
+ if (line.type === "element") root.children.push(...line.children);
946
+ }
947
+ }
948
+ let result = root;
949
+ for (const transformer of transformers) result = transformer?.root?.call(context, result) || result;
950
+ if (grammarState) setLastGrammarStateToMap(result, grammarState);
951
+ return result;
1477
952
  }
1478
953
  function mergeWhitespaceTokens(tokens) {
1479
- return tokens.map((line) => {
1480
- const newLine = [];
1481
- let carryOnContent = "";
1482
- let firstOffset;
1483
- line.forEach((token, idx) => {
1484
- const isDecorated = token.fontStyle && (token.fontStyle & FontStyle.Underline || token.fontStyle & FontStyle.Strikethrough);
1485
- const couldMerge = !isDecorated;
1486
- if (couldMerge && token.content.match(/^\s+$/) && line[idx + 1]) {
1487
- if (firstOffset === void 0)
1488
- firstOffset = token.offset;
1489
- carryOnContent += token.content;
1490
- } else {
1491
- if (carryOnContent) {
1492
- if (couldMerge) {
1493
- newLine.push({
1494
- ...token,
1495
- offset: firstOffset,
1496
- content: carryOnContent + token.content
1497
- });
1498
- } else {
1499
- newLine.push(
1500
- {
1501
- content: carryOnContent,
1502
- offset: firstOffset
1503
- },
1504
- token
1505
- );
1506
- }
1507
- firstOffset = void 0;
1508
- carryOnContent = "";
1509
- } else {
1510
- newLine.push(token);
1511
- }
1512
- }
1513
- });
1514
- return newLine;
1515
- });
954
+ return tokens.map((line) => {
955
+ const newLine = [];
956
+ let carryOnContent = "";
957
+ let firstOffset;
958
+ line.forEach((token, idx) => {
959
+ const couldMerge = !(token.fontStyle && (token.fontStyle & FontStyle.Underline || token.fontStyle & FontStyle.Strikethrough));
960
+ if (couldMerge && token.content.match(/^\s+$/) && line[idx + 1]) {
961
+ if (firstOffset === void 0) firstOffset = token.offset;
962
+ carryOnContent += token.content;
963
+ } else if (carryOnContent) {
964
+ if (couldMerge) newLine.push({
965
+ ...token,
966
+ offset: firstOffset,
967
+ content: carryOnContent + token.content
968
+ });
969
+ else newLine.push({
970
+ content: carryOnContent,
971
+ offset: firstOffset
972
+ }, token);
973
+ firstOffset = void 0;
974
+ carryOnContent = "";
975
+ } else newLine.push(token);
976
+ });
977
+ return newLine;
978
+ });
1516
979
  }
1517
980
  function splitWhitespaceTokens(tokens) {
1518
- return tokens.map((line) => {
1519
- return line.flatMap((token) => {
1520
- if (token.content.match(/^\s+$/))
1521
- return token;
1522
- const match = token.content.match(/^(\s*)(.*?)(\s*)$/);
1523
- if (!match)
1524
- return token;
1525
- const [, leading, content, trailing] = match;
1526
- if (!leading && !trailing)
1527
- return token;
1528
- const expanded = [{
1529
- ...token,
1530
- offset: token.offset + leading.length,
1531
- content
1532
- }];
1533
- if (leading) {
1534
- expanded.unshift({
1535
- content: leading,
1536
- offset: token.offset
1537
- });
1538
- }
1539
- if (trailing) {
1540
- expanded.push({
1541
- content: trailing,
1542
- offset: token.offset + leading.length + content.length
1543
- });
1544
- }
1545
- return expanded;
1546
- });
1547
- });
981
+ return tokens.map((line) => {
982
+ return line.flatMap((token) => {
983
+ if (token.content.match(/^\s+$/)) return token;
984
+ const match = token.content.match(/^(\s*)(.*?)(\s*)$/);
985
+ if (!match) return token;
986
+ const [, leading, content, trailing] = match;
987
+ if (!leading && !trailing) return token;
988
+ const expanded = [{
989
+ ...token,
990
+ offset: token.offset + leading.length,
991
+ content
992
+ }];
993
+ if (leading) expanded.unshift({
994
+ content: leading,
995
+ offset: token.offset
996
+ });
997
+ if (trailing) expanded.push({
998
+ content: trailing,
999
+ offset: token.offset + leading.length + content.length
1000
+ });
1001
+ return expanded;
1002
+ });
1003
+ });
1548
1004
  }
1549
1005
  function mergeAdjacentStyledTokens(tokens) {
1550
- return tokens.map((line) => {
1551
- const newLine = [];
1552
- for (const token of line) {
1553
- if (newLine.length === 0) {
1554
- newLine.push({ ...token });
1555
- continue;
1556
- }
1557
- const prevToken = newLine[newLine.length - 1];
1558
- const prevStyle = stringifyTokenStyle(prevToken.htmlStyle || getTokenStyleObject(prevToken));
1559
- const currentStyle = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
1560
- const isPrevDecorated = prevToken.fontStyle && (prevToken.fontStyle & FontStyle.Underline || prevToken.fontStyle & FontStyle.Strikethrough);
1561
- const isDecorated = token.fontStyle && (token.fontStyle & FontStyle.Underline || token.fontStyle & FontStyle.Strikethrough);
1562
- if (!isPrevDecorated && !isDecorated && prevStyle === currentStyle) {
1563
- prevToken.content += token.content;
1564
- } else {
1565
- newLine.push({ ...token });
1566
- }
1567
- }
1568
- return newLine;
1569
- });
1006
+ return tokens.map((line) => {
1007
+ const newLine = [];
1008
+ for (const token of line) {
1009
+ if (newLine.length === 0) {
1010
+ newLine.push({ ...token });
1011
+ continue;
1012
+ }
1013
+ const prevToken = newLine[newLine.length - 1];
1014
+ const prevStyle = stringifyTokenStyle(prevToken.htmlStyle || getTokenStyleObject(prevToken));
1015
+ const currentStyle = stringifyTokenStyle(token.htmlStyle || getTokenStyleObject(token));
1016
+ const isPrevDecorated = prevToken.fontStyle && (prevToken.fontStyle & FontStyle.Underline || prevToken.fontStyle & FontStyle.Strikethrough);
1017
+ const isDecorated = token.fontStyle && (token.fontStyle & FontStyle.Underline || token.fontStyle & FontStyle.Strikethrough);
1018
+ if (!isPrevDecorated && !isDecorated && prevStyle === currentStyle) prevToken.content += token.content;
1019
+ else newLine.push({ ...token });
1020
+ }
1021
+ return newLine;
1022
+ });
1570
1023
  }
1571
1024
 
1025
+ //#endregion
1026
+ //#region src/highlight/code-to-html.ts
1572
1027
  const hastToHtml = toHtml;
1573
- function codeToHtml(internal, code, options) {
1574
- const context = {
1575
- meta: {},
1576
- options,
1577
- codeToHast: (_code, _options) => codeToHast(internal, _code, _options),
1578
- codeToTokens: (_code, _options) => codeToTokens(internal, _code, _options)
1579
- };
1580
- let result = hastToHtml(codeToHast(internal, code, options, context));
1581
- for (const transformer of getTransformers(options))
1582
- result = transformer.postprocess?.call(context, result, options) || result;
1583
- return result;
1584
- }
1585
-
1586
- const VSCODE_FALLBACK_EDITOR_FG = { light: "#333333", dark: "#bbbbbb" };
1587
- const VSCODE_FALLBACK_EDITOR_BG = { light: "#fffffe", dark: "#1e1e1e" };
1588
- const RESOLVED_KEY = "__shiki_resolved";
1589
- function normalizeTheme(rawTheme) {
1590
- if (rawTheme?.[RESOLVED_KEY])
1591
- return rawTheme;
1592
- const theme = {
1593
- ...rawTheme
1594
- };
1595
- if (theme.tokenColors && !theme.settings) {
1596
- theme.settings = theme.tokenColors;
1597
- delete theme.tokenColors;
1598
- }
1599
- theme.type ||= "dark";
1600
- theme.colorReplacements = { ...theme.colorReplacements };
1601
- theme.settings ||= [];
1602
- let { bg, fg } = theme;
1603
- if (!bg || !fg) {
1604
- const globalSetting = theme.settings ? theme.settings.find((s) => !s.name && !s.scope) : void 0;
1605
- if (globalSetting?.settings?.foreground)
1606
- fg = globalSetting.settings.foreground;
1607
- if (globalSetting?.settings?.background)
1608
- bg = globalSetting.settings.background;
1609
- if (!fg && theme?.colors?.["editor.foreground"])
1610
- fg = theme.colors["editor.foreground"];
1611
- if (!bg && theme?.colors?.["editor.background"])
1612
- bg = theme.colors["editor.background"];
1613
- if (!fg)
1614
- fg = theme.type === "light" ? VSCODE_FALLBACK_EDITOR_FG.light : VSCODE_FALLBACK_EDITOR_FG.dark;
1615
- if (!bg)
1616
- bg = theme.type === "light" ? VSCODE_FALLBACK_EDITOR_BG.light : VSCODE_FALLBACK_EDITOR_BG.dark;
1617
- theme.fg = fg;
1618
- theme.bg = bg;
1619
- }
1620
- if (!(theme.settings[0] && theme.settings[0].settings && !theme.settings[0].scope)) {
1621
- theme.settings.unshift({
1622
- settings: {
1623
- foreground: theme.fg,
1624
- background: theme.bg
1625
- }
1626
- });
1627
- }
1628
- let replacementCount = 0;
1629
- const replacementMap = /* @__PURE__ */ new Map();
1630
- function getReplacementColor(value) {
1631
- if (replacementMap.has(value))
1632
- return replacementMap.get(value);
1633
- replacementCount += 1;
1634
- const hex = `#${replacementCount.toString(16).padStart(8, "0").toLowerCase()}`;
1635
- if (theme.colorReplacements?.[`#${hex}`])
1636
- return getReplacementColor(value);
1637
- replacementMap.set(value, hex);
1638
- return hex;
1639
- }
1640
- theme.settings = theme.settings.map((setting) => {
1641
- const replaceFg = setting.settings?.foreground && !setting.settings.foreground.startsWith("#");
1642
- const replaceBg = setting.settings?.background && !setting.settings.background.startsWith("#");
1643
- if (!replaceFg && !replaceBg)
1644
- return setting;
1645
- const clone = {
1646
- ...setting,
1647
- settings: {
1648
- ...setting.settings
1649
- }
1650
- };
1651
- if (replaceFg) {
1652
- const replacement = getReplacementColor(setting.settings.foreground);
1653
- theme.colorReplacements[replacement] = setting.settings.foreground;
1654
- clone.settings.foreground = replacement;
1655
- }
1656
- if (replaceBg) {
1657
- const replacement = getReplacementColor(setting.settings.background);
1658
- theme.colorReplacements[replacement] = setting.settings.background;
1659
- clone.settings.background = replacement;
1660
- }
1661
- return clone;
1662
- });
1663
- for (const key of Object.keys(theme.colors || {})) {
1664
- if (key === "editor.foreground" || key === "editor.background" || key.startsWith("terminal.ansi")) {
1665
- if (!theme.colors[key]?.startsWith("#")) {
1666
- const replacement = getReplacementColor(theme.colors[key]);
1667
- theme.colorReplacements[replacement] = theme.colors[key];
1668
- theme.colors[key] = replacement;
1669
- }
1670
- }
1671
- }
1672
- Object.defineProperty(theme, RESOLVED_KEY, {
1673
- enumerable: false,
1674
- writable: false,
1675
- value: true
1676
- });
1677
- return theme;
1678
- }
1679
-
1680
- async function resolveLangs(langs) {
1681
- return Array.from(new Set((await Promise.all(
1682
- langs.filter((l) => !isSpecialLang(l)).map(async (lang) => await normalizeGetter(lang).then((r) => Array.isArray(r) ? r : [r]))
1683
- )).flat()));
1684
- }
1685
- async function resolveThemes(themes) {
1686
- const resolved = await Promise.all(
1687
- themes.map(
1688
- async (theme) => isSpecialTheme(theme) ? null : normalizeTheme(await normalizeGetter(theme))
1689
- )
1690
- );
1691
- return resolved.filter((i) => !!i);
1692
- }
1693
-
1694
- let _emitDeprecation = 3;
1695
- let _emitError = false;
1696
- function enableDeprecationWarnings(emitDeprecation = true, emitError = false) {
1697
- _emitDeprecation = emitDeprecation;
1698
- _emitError = emitError;
1699
- }
1700
- function warnDeprecated(message, version = 3) {
1701
- if (!_emitDeprecation)
1702
- return;
1703
- if (typeof _emitDeprecation === "number" && version > _emitDeprecation)
1704
- return;
1705
- if (_emitError) {
1706
- throw new Error(`[SHIKI DEPRECATE]: ${message}`);
1707
- } else {
1708
- console.trace(`[SHIKI DEPRECATE]: ${message}`);
1709
- }
1710
- }
1711
-
1712
- class ShikiError extends Error {
1713
- constructor(message) {
1714
- super(message);
1715
- this.name = "ShikiError";
1716
- }
1717
- }
1718
-
1719
- function resolveLangAlias(name, alias) {
1720
- if (!alias)
1721
- return name;
1722
- if (alias[name]) {
1723
- const resolved = /* @__PURE__ */ new Set([name]);
1724
- while (alias[name]) {
1725
- name = alias[name];
1726
- if (resolved.has(name))
1727
- throw new ShikiError(`Circular alias \`${Array.from(resolved).join(" -> ")} -> ${name}\``);
1728
- resolved.add(name);
1729
- }
1730
- }
1731
- return name;
1732
- }
1733
-
1734
- class Registry extends Registry$1 {
1735
- constructor(_resolver, _themes, _langs, _alias = {}) {
1736
- super(_resolver);
1737
- this._resolver = _resolver;
1738
- this._themes = _themes;
1739
- this._langs = _langs;
1740
- this._alias = _alias;
1741
- this._themes.map((t) => this.loadTheme(t));
1742
- this.loadLanguages(this._langs);
1743
- }
1744
- _resolvedThemes = /* @__PURE__ */ new Map();
1745
- _resolvedGrammars = /* @__PURE__ */ new Map();
1746
- _langMap = /* @__PURE__ */ new Map();
1747
- _langGraph = /* @__PURE__ */ new Map();
1748
- _textmateThemeCache = /* @__PURE__ */ new WeakMap();
1749
- _loadedThemesCache = null;
1750
- _loadedLanguagesCache = null;
1751
- getTheme(theme) {
1752
- if (typeof theme === "string")
1753
- return this._resolvedThemes.get(theme);
1754
- else
1755
- return this.loadTheme(theme);
1756
- }
1757
- loadTheme(theme) {
1758
- const _theme = normalizeTheme(theme);
1759
- if (_theme.name) {
1760
- this._resolvedThemes.set(_theme.name, _theme);
1761
- this._loadedThemesCache = null;
1762
- }
1763
- return _theme;
1764
- }
1765
- getLoadedThemes() {
1766
- if (!this._loadedThemesCache)
1767
- this._loadedThemesCache = [...this._resolvedThemes.keys()];
1768
- return this._loadedThemesCache;
1769
- }
1770
- // Override and re-implement this method to cache the textmate themes as `TextMateTheme.createFromRawTheme`
1771
- // is expensive. Themes can switch often especially for dual-theme support.
1772
- //
1773
- // The parent class also accepts `colorMap` as the second parameter, but since we don't use that,
1774
- // we omit here so it's easier to cache the themes.
1775
- setTheme(theme) {
1776
- let textmateTheme = this._textmateThemeCache.get(theme);
1777
- if (!textmateTheme) {
1778
- textmateTheme = Theme.createFromRawTheme(theme);
1779
- this._textmateThemeCache.set(theme, textmateTheme);
1780
- }
1781
- this._syncRegistry.setTheme(textmateTheme);
1782
- }
1783
- getGrammar(name) {
1784
- name = resolveLangAlias(name, this._alias);
1785
- return this._resolvedGrammars.get(name);
1786
- }
1787
- loadLanguage(lang) {
1788
- if (this.getGrammar(lang.name))
1789
- return;
1790
- const embeddedLazilyBy = new Set(
1791
- [...this._langMap.values()].filter((i) => i.embeddedLangsLazy?.includes(lang.name))
1792
- );
1793
- this._resolver.addLanguage(lang);
1794
- const grammarConfig = {
1795
- balancedBracketSelectors: lang.balancedBracketSelectors || ["*"],
1796
- unbalancedBracketSelectors: lang.unbalancedBracketSelectors || []
1797
- };
1798
- this._syncRegistry._rawGrammars.set(lang.scopeName, lang);
1799
- const g = this.loadGrammarWithConfiguration(lang.scopeName, 1, grammarConfig);
1800
- g.name = lang.name;
1801
- this._resolvedGrammars.set(lang.name, g);
1802
- if (lang.aliases) {
1803
- lang.aliases.forEach((alias) => {
1804
- this._alias[alias] = lang.name;
1805
- });
1806
- }
1807
- this._loadedLanguagesCache = null;
1808
- if (embeddedLazilyBy.size) {
1809
- for (const e of embeddedLazilyBy) {
1810
- this._resolvedGrammars.delete(e.name);
1811
- this._loadedLanguagesCache = null;
1812
- this._syncRegistry?._injectionGrammars?.delete(e.scopeName);
1813
- this._syncRegistry?._grammars?.delete(e.scopeName);
1814
- this.loadLanguage(this._langMap.get(e.name));
1815
- }
1816
- }
1817
- }
1818
- dispose() {
1819
- super.dispose();
1820
- this._resolvedThemes.clear();
1821
- this._resolvedGrammars.clear();
1822
- this._langMap.clear();
1823
- this._langGraph.clear();
1824
- this._loadedThemesCache = null;
1825
- }
1826
- loadLanguages(langs) {
1827
- for (const lang of langs)
1828
- this.resolveEmbeddedLanguages(lang);
1829
- const langsGraphArray = Array.from(this._langGraph.entries());
1830
- const missingLangs = langsGraphArray.filter(([_, lang]) => !lang);
1831
- if (missingLangs.length) {
1832
- const dependents = langsGraphArray.filter(([_, lang]) => {
1833
- if (!lang)
1834
- return false;
1835
- const embedded = lang.embeddedLanguages || lang.embeddedLangs;
1836
- return embedded?.some((l) => missingLangs.map(([name]) => name).includes(l));
1837
- }).filter((lang) => !missingLangs.includes(lang));
1838
- throw new ShikiError(`Missing languages ${missingLangs.map(([name]) => `\`${name}\``).join(", ")}, required by ${dependents.map(([name]) => `\`${name}\``).join(", ")}`);
1839
- }
1840
- for (const [_, lang] of langsGraphArray)
1841
- this._resolver.addLanguage(lang);
1842
- for (const [_, lang] of langsGraphArray)
1843
- this.loadLanguage(lang);
1844
- }
1845
- getLoadedLanguages() {
1846
- if (!this._loadedLanguagesCache) {
1847
- this._loadedLanguagesCache = [
1848
- .../* @__PURE__ */ new Set([...this._resolvedGrammars.keys(), ...Object.keys(this._alias)])
1849
- ];
1850
- }
1851
- return this._loadedLanguagesCache;
1852
- }
1853
- resolveEmbeddedLanguages(lang) {
1854
- this._langMap.set(lang.name, lang);
1855
- this._langGraph.set(lang.name, lang);
1856
- const embedded = lang.embeddedLanguages ?? lang.embeddedLangs;
1857
- if (embedded) {
1858
- for (const embeddedLang of embedded)
1859
- this._langGraph.set(embeddedLang, this._langMap.get(embeddedLang));
1860
- }
1861
- }
1862
- }
1863
-
1864
- class Resolver {
1865
- _langs = /* @__PURE__ */ new Map();
1866
- _scopeToLang = /* @__PURE__ */ new Map();
1867
- _injections = /* @__PURE__ */ new Map();
1868
- _onigLib;
1869
- constructor(engine, langs) {
1870
- this._onigLib = {
1871
- createOnigScanner: (patterns) => engine.createScanner(patterns),
1872
- createOnigString: (s) => engine.createString(s)
1873
- };
1874
- langs.forEach((i) => this.addLanguage(i));
1875
- }
1876
- get onigLib() {
1877
- return this._onigLib;
1878
- }
1879
- getLangRegistration(langIdOrAlias) {
1880
- return this._langs.get(langIdOrAlias);
1881
- }
1882
- loadGrammar(scopeName) {
1883
- return this._scopeToLang.get(scopeName);
1884
- }
1885
- addLanguage(l) {
1886
- this._langs.set(l.name, l);
1887
- if (l.aliases) {
1888
- l.aliases.forEach((a) => {
1889
- this._langs.set(a, l);
1890
- });
1891
- }
1892
- this._scopeToLang.set(l.scopeName, l);
1893
- if (l.injectTo) {
1894
- l.injectTo.forEach((i) => {
1895
- if (!this._injections.get(i))
1896
- this._injections.set(i, []);
1897
- this._injections.get(i).push(l.scopeName);
1898
- });
1899
- }
1900
- }
1901
- getInjections(scopeName) {
1902
- const scopeParts = scopeName.split(".");
1903
- let injections = [];
1904
- for (let i = 1; i <= scopeParts.length; i++) {
1905
- const subScopeName = scopeParts.slice(0, i).join(".");
1906
- injections = [...injections, ...this._injections.get(subScopeName) || []];
1907
- }
1908
- return injections;
1909
- }
1910
- }
1911
-
1912
- let instancesCount = 0;
1913
- function createShikiInternalSync(options) {
1914
- instancesCount += 1;
1915
- if (options.warnings !== false && instancesCount >= 10 && instancesCount % 10 === 0)
1916
- console.warn(`[Shiki] ${instancesCount} instances have been created. Shiki is supposed to be used as a singleton, consider refactoring your code to cache your highlighter instance; Or call \`highlighter.dispose()\` to release unused instances.`);
1917
- let isDisposed = false;
1918
- if (!options.engine)
1919
- throw new ShikiError("`engine` option is required for synchronous mode");
1920
- const langs = (options.langs || []).flat(1);
1921
- const themes = (options.themes || []).flat(1).map(normalizeTheme);
1922
- const resolver = new Resolver(options.engine, langs);
1923
- const _registry = new Registry(resolver, themes, langs, options.langAlias);
1924
- let _lastTheme;
1925
- function resolveLangAlias$1(name) {
1926
- return resolveLangAlias(name, options.langAlias);
1927
- }
1928
- function getLanguage(name) {
1929
- ensureNotDisposed();
1930
- const _lang = _registry.getGrammar(typeof name === "string" ? name : name.name);
1931
- if (!_lang)
1932
- throw new ShikiError(`Language \`${name}\` not found, you may need to load it first`);
1933
- return _lang;
1934
- }
1935
- function getTheme(name) {
1936
- if (name === "none")
1937
- return { bg: "", fg: "", name: "none", settings: [], type: "dark" };
1938
- ensureNotDisposed();
1939
- const _theme = _registry.getTheme(name);
1940
- if (!_theme)
1941
- throw new ShikiError(`Theme \`${name}\` not found, you may need to load it first`);
1942
- return _theme;
1943
- }
1944
- function setTheme(name) {
1945
- ensureNotDisposed();
1946
- const theme = getTheme(name);
1947
- if (_lastTheme !== name) {
1948
- _registry.setTheme(theme);
1949
- _lastTheme = name;
1950
- }
1951
- const colorMap = _registry.getColorMap();
1952
- return {
1953
- theme,
1954
- colorMap
1955
- };
1956
- }
1957
- function getLoadedThemes() {
1958
- ensureNotDisposed();
1959
- return _registry.getLoadedThemes();
1960
- }
1961
- function getLoadedLanguages() {
1962
- ensureNotDisposed();
1963
- return _registry.getLoadedLanguages();
1964
- }
1965
- function loadLanguageSync(...langs2) {
1966
- ensureNotDisposed();
1967
- _registry.loadLanguages(langs2.flat(1));
1968
- }
1969
- async function loadLanguage(...langs2) {
1970
- return loadLanguageSync(await resolveLangs(langs2));
1971
- }
1972
- function loadThemeSync(...themes2) {
1973
- ensureNotDisposed();
1974
- for (const theme of themes2.flat(1)) {
1975
- _registry.loadTheme(theme);
1976
- }
1977
- }
1978
- async function loadTheme(...themes2) {
1979
- ensureNotDisposed();
1980
- return loadThemeSync(await resolveThemes(themes2));
1981
- }
1982
- function ensureNotDisposed() {
1983
- if (isDisposed)
1984
- throw new ShikiError("Shiki instance has been disposed");
1985
- }
1986
- function dispose() {
1987
- if (isDisposed)
1988
- return;
1989
- isDisposed = true;
1990
- _registry.dispose();
1991
- instancesCount -= 1;
1992
- }
1993
- return {
1994
- setTheme,
1995
- getTheme,
1996
- getLanguage,
1997
- getLoadedThemes,
1998
- getLoadedLanguages,
1999
- resolveLangAlias: resolveLangAlias$1,
2000
- loadLanguage,
2001
- loadLanguageSync,
2002
- loadTheme,
2003
- loadThemeSync,
2004
- dispose,
2005
- [Symbol.dispose]: dispose
2006
- };
2007
- }
2008
-
2009
- async function createShikiInternal(options) {
2010
- if (!options.engine) {
2011
- warnDeprecated("`engine` option is required. Use `createOnigurumaEngine` or `createJavaScriptRegexEngine` to create an engine.");
2012
- }
2013
- const [
2014
- themes,
2015
- langs,
2016
- engine
2017
- ] = await Promise.all([
2018
- resolveThemes(options.themes || []),
2019
- resolveLangs(options.langs || []),
2020
- options.engine
2021
- ]);
2022
- return createShikiInternalSync({
2023
- ...options,
2024
- themes,
2025
- langs,
2026
- engine
2027
- });
1028
+ /**
1029
+ * Get highlighted code in HTML.
1030
+ */
1031
+ function codeToHtml(primitive, code, options) {
1032
+ const context = {
1033
+ meta: {},
1034
+ options,
1035
+ codeToHast: (_code, _options) => codeToHast(primitive, _code, _options),
1036
+ codeToTokens: (_code, _options) => codeToTokens(primitive, _code, _options)
1037
+ };
1038
+ let result = hastToHtml(codeToHast(primitive, code, options, context));
1039
+ for (const transformer of getTransformers(options)) result = transformer.postprocess?.call(context, result, options) || result;
1040
+ return result;
2028
1041
  }
2029
1042
 
1043
+ //#endregion
1044
+ //#region src/constructors/highlighter.ts
1045
+ /**
1046
+ * Create a Shiki core highlighter instance, with no languages or themes bundled.
1047
+ * Wasm and each language and theme must be loaded manually.
1048
+ *
1049
+ * @see http://shiki.style/guide/bundles#fine-grained-bundle
1050
+ */
2030
1051
  async function createHighlighterCore(options) {
2031
- const internal = await createShikiInternal(options);
2032
- return {
2033
- getLastGrammarState: (...args) => getLastGrammarState(internal, ...args),
2034
- codeToTokensBase: (code, options2) => codeToTokensBase(internal, code, options2),
2035
- codeToTokensWithThemes: (code, options2) => codeToTokensWithThemes(internal, code, options2),
2036
- codeToTokens: (code, options2) => codeToTokens(internal, code, options2),
2037
- codeToHast: (code, options2) => codeToHast(internal, code, options2),
2038
- codeToHtml: (code, options2) => codeToHtml(internal, code, options2),
2039
- getBundledLanguages: () => ({}),
2040
- getBundledThemes: () => ({}),
2041
- ...internal,
2042
- getInternalContext: () => internal
2043
- };
2044
- }
1052
+ const primitive = await createShikiPrimitiveAsync$1(options);
1053
+ return {
1054
+ getLastGrammarState: (...args) => getLastGrammarState(primitive, ...args),
1055
+ codeToTokensBase: (code, options) => codeToTokensBase(primitive, code, options),
1056
+ codeToTokensWithThemes: (code, options) => codeToTokensWithThemes$1(primitive, code, options),
1057
+ codeToTokens: (code, options) => codeToTokens(primitive, code, options),
1058
+ codeToHast: (code, options) => codeToHast(primitive, code, options),
1059
+ codeToHtml: (code, options) => codeToHtml(primitive, code, options),
1060
+ getBundledLanguages: () => ({}),
1061
+ getBundledThemes: () => ({}),
1062
+ ...primitive,
1063
+ getInternalContext: () => primitive
1064
+ };
1065
+ }
1066
+ /**
1067
+ * Create a Shiki core highlighter instance, with no languages or themes bundled.
1068
+ * Wasm and each language and theme must be loaded manually.
1069
+ *
1070
+ * Synchronous version of `createHighlighterCore`, which requires to provide the engine and all themes and languages upfront.
1071
+ *
1072
+ * @see http://shiki.style/guide/bundles#fine-grained-bundle
1073
+ */
2045
1074
  function createHighlighterCoreSync(options) {
2046
- const internal = createShikiInternalSync(options);
2047
- return {
2048
- getLastGrammarState: (...args) => getLastGrammarState(internal, ...args),
2049
- codeToTokensBase: (code, options2) => codeToTokensBase(internal, code, options2),
2050
- codeToTokensWithThemes: (code, options2) => codeToTokensWithThemes(internal, code, options2),
2051
- codeToTokens: (code, options2) => codeToTokens(internal, code, options2),
2052
- codeToHast: (code, options2) => codeToHast(internal, code, options2),
2053
- codeToHtml: (code, options2) => codeToHtml(internal, code, options2),
2054
- getBundledLanguages: () => ({}),
2055
- getBundledThemes: () => ({}),
2056
- ...internal,
2057
- getInternalContext: () => internal
2058
- };
1075
+ const internal = createShikiPrimitive$1(options);
1076
+ return {
1077
+ getLastGrammarState: (...args) => getLastGrammarState(internal, ...args),
1078
+ codeToTokensBase: (code, options) => codeToTokensBase(internal, code, options),
1079
+ codeToTokensWithThemes: (code, options) => codeToTokensWithThemes$1(internal, code, options),
1080
+ codeToTokens: (code, options) => codeToTokens(internal, code, options),
1081
+ codeToHast: (code, options) => codeToHast(internal, code, options),
1082
+ codeToHtml: (code, options) => codeToHtml(internal, code, options),
1083
+ getBundledLanguages: () => ({}),
1084
+ getBundledThemes: () => ({}),
1085
+ ...internal,
1086
+ getInternalContext: () => internal
1087
+ };
2059
1088
  }
2060
1089
  function makeSingletonHighlighterCore(createHighlighter) {
2061
- let _shiki;
2062
- async function getSingletonHighlighterCore2(options) {
2063
- if (!_shiki) {
2064
- _shiki = createHighlighter({
2065
- ...options,
2066
- themes: options.themes || [],
2067
- langs: options.langs || []
2068
- });
2069
- return _shiki;
2070
- } else {
2071
- const s = await _shiki;
2072
- await Promise.all([
2073
- s.loadTheme(...options.themes || []),
2074
- s.loadLanguage(...options.langs || [])
2075
- ]);
2076
- return s;
2077
- }
2078
- }
2079
- return getSingletonHighlighterCore2;
1090
+ let _shiki;
1091
+ async function getSingletonHighlighterCore(options) {
1092
+ if (!_shiki) {
1093
+ _shiki = createHighlighter({
1094
+ ...options,
1095
+ themes: options.themes || [],
1096
+ langs: options.langs || []
1097
+ });
1098
+ return _shiki;
1099
+ } else {
1100
+ const s = await _shiki;
1101
+ await Promise.all([s.loadTheme(...options.themes || []), s.loadLanguage(...options.langs || [])]);
1102
+ return s;
1103
+ }
1104
+ }
1105
+ return getSingletonHighlighterCore;
2080
1106
  }
2081
1107
  const getSingletonHighlighterCore = /* @__PURE__ */ makeSingletonHighlighterCore(createHighlighterCore);
2082
1108
 
1109
+ //#endregion
1110
+ //#region src/constructors/bundle-factory.ts
2083
1111
  function createBundledHighlighter(options) {
2084
- const bundledLanguages = options.langs;
2085
- const bundledThemes = options.themes;
2086
- const engine = options.engine;
2087
- async function createHighlighter(options2) {
2088
- function resolveLang(lang) {
2089
- if (typeof lang === "string") {
2090
- lang = options2.langAlias?.[lang] || lang;
2091
- if (isSpecialLang(lang))
2092
- return [];
2093
- const bundle = bundledLanguages[lang];
2094
- if (!bundle)
2095
- throw new ShikiError$1(`Language \`${lang}\` is not included in this bundle. You may want to load it from external source.`);
2096
- return bundle;
2097
- }
2098
- return lang;
2099
- }
2100
- function resolveTheme(theme) {
2101
- if (isSpecialTheme(theme))
2102
- return "none";
2103
- if (typeof theme === "string") {
2104
- const bundle = bundledThemes[theme];
2105
- if (!bundle)
2106
- throw new ShikiError$1(`Theme \`${theme}\` is not included in this bundle. You may want to load it from external source.`);
2107
- return bundle;
2108
- }
2109
- return theme;
2110
- }
2111
- const _themes = (options2.themes ?? []).map((i) => resolveTheme(i));
2112
- const langs = (options2.langs ?? []).map((i) => resolveLang(i));
2113
- const core = await createHighlighterCore({
2114
- engine: options2.engine ?? engine(),
2115
- ...options2,
2116
- themes: _themes,
2117
- langs
2118
- });
2119
- return {
2120
- ...core,
2121
- loadLanguage(...langs2) {
2122
- return core.loadLanguage(...langs2.map(resolveLang));
2123
- },
2124
- loadTheme(...themes) {
2125
- return core.loadTheme(...themes.map(resolveTheme));
2126
- },
2127
- getBundledLanguages() {
2128
- return bundledLanguages;
2129
- },
2130
- getBundledThemes() {
2131
- return bundledThemes;
2132
- }
2133
- };
2134
- }
2135
- return createHighlighter;
1112
+ const bundledLanguages = options.langs;
1113
+ const bundledThemes = options.themes;
1114
+ const engine = options.engine;
1115
+ async function createHighlighter(options) {
1116
+ function resolveLang(lang) {
1117
+ if (typeof lang === "string") {
1118
+ lang = options.langAlias?.[lang] || lang;
1119
+ if (isSpecialLang(lang)) return [];
1120
+ const bundle = bundledLanguages[lang];
1121
+ if (!bundle) throw new ShikiError$1(`Language \`${lang}\` is not included in this bundle. You may want to load it from external source.`);
1122
+ return bundle;
1123
+ }
1124
+ return lang;
1125
+ }
1126
+ function resolveTheme(theme) {
1127
+ if (isSpecialTheme(theme)) return "none";
1128
+ if (typeof theme === "string") {
1129
+ const bundle = bundledThemes[theme];
1130
+ if (!bundle) throw new ShikiError$1(`Theme \`${theme}\` is not included in this bundle. You may want to load it from external source.`);
1131
+ return bundle;
1132
+ }
1133
+ return theme;
1134
+ }
1135
+ const _themes = (options.themes ?? []).map((i) => resolveTheme(i));
1136
+ const langs = (options.langs ?? []).map((i) => resolveLang(i));
1137
+ const core = await createHighlighterCore({
1138
+ engine: options.engine ?? engine(),
1139
+ ...options,
1140
+ themes: _themes,
1141
+ langs
1142
+ });
1143
+ return {
1144
+ ...core,
1145
+ loadLanguage(...langs) {
1146
+ return core.loadLanguage(...langs.map(resolveLang));
1147
+ },
1148
+ loadTheme(...themes) {
1149
+ return core.loadTheme(...themes.map(resolveTheme));
1150
+ },
1151
+ getBundledLanguages() {
1152
+ return bundledLanguages;
1153
+ },
1154
+ getBundledThemes() {
1155
+ return bundledThemes;
1156
+ }
1157
+ };
1158
+ }
1159
+ return createHighlighter;
2136
1160
  }
2137
1161
  function makeSingletonHighlighter(createHighlighter) {
2138
- let _shiki;
2139
- async function getSingletonHighlighter(options = {}) {
2140
- if (!_shiki) {
2141
- _shiki = createHighlighter({
2142
- ...options,
2143
- themes: [],
2144
- langs: []
2145
- });
2146
- const s = await _shiki;
2147
- await Promise.all([
2148
- s.loadTheme(...options.themes || []),
2149
- s.loadLanguage(...options.langs || [])
2150
- ]);
2151
- return s;
2152
- } else {
2153
- const s = await _shiki;
2154
- await Promise.all([
2155
- s.loadTheme(...options.themes || []),
2156
- s.loadLanguage(...options.langs || [])
2157
- ]);
2158
- return s;
2159
- }
2160
- }
2161
- return getSingletonHighlighter;
1162
+ let _shiki;
1163
+ async function getSingletonHighlighter(options = {}) {
1164
+ if (!_shiki) {
1165
+ _shiki = createHighlighter({
1166
+ ...options,
1167
+ themes: [],
1168
+ langs: []
1169
+ });
1170
+ const s = await _shiki;
1171
+ await Promise.all([s.loadTheme(...options.themes || []), s.loadLanguage(...options.langs || [])]);
1172
+ return s;
1173
+ } else {
1174
+ const s = await _shiki;
1175
+ await Promise.all([s.loadTheme(...options.themes || []), s.loadLanguage(...options.langs || [])]);
1176
+ return s;
1177
+ }
1178
+ }
1179
+ return getSingletonHighlighter;
2162
1180
  }
2163
1181
  function createSingletonShorthands(createHighlighter, config) {
2164
- const getSingletonHighlighter = makeSingletonHighlighter(createHighlighter);
2165
- async function get(code, options) {
2166
- const shiki = await getSingletonHighlighter({
2167
- langs: [options.lang],
2168
- themes: "theme" in options ? [options.theme] : Object.values(options.themes)
2169
- });
2170
- const langs = await config?.guessEmbeddedLanguages?.(code, options.lang, shiki);
2171
- if (langs) {
2172
- await shiki.loadLanguage(...langs);
2173
- }
2174
- return shiki;
2175
- }
2176
- return {
2177
- getSingletonHighlighter(options) {
2178
- return getSingletonHighlighter(options);
2179
- },
2180
- async codeToHtml(code, options) {
2181
- const shiki = await get(code, options);
2182
- return shiki.codeToHtml(code, options);
2183
- },
2184
- async codeToHast(code, options) {
2185
- const shiki = await get(code, options);
2186
- return shiki.codeToHast(code, options);
2187
- },
2188
- async codeToTokens(code, options) {
2189
- const shiki = await get(code, options);
2190
- return shiki.codeToTokens(code, options);
2191
- },
2192
- async codeToTokensBase(code, options) {
2193
- const shiki = await get(code, options);
2194
- return shiki.codeToTokensBase(code, options);
2195
- },
2196
- async codeToTokensWithThemes(code, options) {
2197
- const shiki = await get(code, options);
2198
- return shiki.codeToTokensWithThemes(code, options);
2199
- },
2200
- async getLastGrammarState(code, options) {
2201
- const shiki = await getSingletonHighlighter({
2202
- langs: [options.lang],
2203
- themes: [options.theme]
2204
- });
2205
- return shiki.getLastGrammarState(code, options);
2206
- }
2207
- };
1182
+ const getSingletonHighlighter = makeSingletonHighlighter(createHighlighter);
1183
+ async function get(code, options) {
1184
+ const shiki = await getSingletonHighlighter({
1185
+ langs: [options.lang],
1186
+ themes: "theme" in options ? [options.theme] : Object.values(options.themes)
1187
+ });
1188
+ const langs = await config?.guessEmbeddedLanguages?.(code, options.lang, shiki);
1189
+ if (langs) await shiki.loadLanguage(...langs);
1190
+ return shiki;
1191
+ }
1192
+ return {
1193
+ getSingletonHighlighter(options) {
1194
+ return getSingletonHighlighter(options);
1195
+ },
1196
+ async codeToHtml(code, options) {
1197
+ return (await get(code, options)).codeToHtml(code, options);
1198
+ },
1199
+ async codeToHast(code, options) {
1200
+ return (await get(code, options)).codeToHast(code, options);
1201
+ },
1202
+ async codeToTokens(code, options) {
1203
+ return (await get(code, options)).codeToTokens(code, options);
1204
+ },
1205
+ async codeToTokensBase(code, options) {
1206
+ return (await get(code, options)).codeToTokensBase(code, options);
1207
+ },
1208
+ async codeToTokensWithThemes(code, options) {
1209
+ return (await get(code, options)).codeToTokensWithThemes(code, options);
1210
+ },
1211
+ async getLastGrammarState(code, options) {
1212
+ return (await getSingletonHighlighter({
1213
+ langs: [options.lang],
1214
+ themes: [options.theme]
1215
+ })).getLastGrammarState(code, options);
1216
+ }
1217
+ };
2208
1218
  }
2209
- const createdBundledHighlighter = createBundledHighlighter;
2210
1219
 
1220
+ //#endregion
1221
+ //#region src/theme-css-variables.ts
1222
+ /**
1223
+ * A factory function to create a css-variable-based theme
1224
+ *
1225
+ * @see https://shiki.style/guide/theme-colors#css-variables-theme
1226
+ */
2211
1227
  function createCssVariablesTheme(options = {}) {
2212
- const {
2213
- name = "css-variables",
2214
- variablePrefix = "--shiki-",
2215
- fontStyle = true
2216
- } = options;
2217
- const variable = (name2) => {
2218
- if (options.variableDefaults?.[name2])
2219
- return `var(${variablePrefix}${name2}, ${options.variableDefaults[name2]})`;
2220
- return `var(${variablePrefix}${name2})`;
2221
- };
2222
- const theme = {
2223
- name,
2224
- type: "dark",
2225
- colors: {
2226
- "editor.foreground": variable("foreground"),
2227
- "editor.background": variable("background"),
2228
- "terminal.ansiBlack": variable("ansi-black"),
2229
- "terminal.ansiRed": variable("ansi-red"),
2230
- "terminal.ansiGreen": variable("ansi-green"),
2231
- "terminal.ansiYellow": variable("ansi-yellow"),
2232
- "terminal.ansiBlue": variable("ansi-blue"),
2233
- "terminal.ansiMagenta": variable("ansi-magenta"),
2234
- "terminal.ansiCyan": variable("ansi-cyan"),
2235
- "terminal.ansiWhite": variable("ansi-white"),
2236
- "terminal.ansiBrightBlack": variable("ansi-bright-black"),
2237
- "terminal.ansiBrightRed": variable("ansi-bright-red"),
2238
- "terminal.ansiBrightGreen": variable("ansi-bright-green"),
2239
- "terminal.ansiBrightYellow": variable("ansi-bright-yellow"),
2240
- "terminal.ansiBrightBlue": variable("ansi-bright-blue"),
2241
- "terminal.ansiBrightMagenta": variable("ansi-bright-magenta"),
2242
- "terminal.ansiBrightCyan": variable("ansi-bright-cyan"),
2243
- "terminal.ansiBrightWhite": variable("ansi-bright-white")
2244
- },
2245
- tokenColors: [
2246
- {
2247
- scope: [
2248
- "keyword.operator.accessor",
2249
- "meta.group.braces.round.function.arguments",
2250
- "meta.template.expression",
2251
- "markup.fenced_code meta.embedded.block"
2252
- ],
2253
- settings: {
2254
- foreground: variable("foreground")
2255
- }
2256
- },
2257
- {
2258
- scope: "emphasis",
2259
- settings: {
2260
- fontStyle: "italic"
2261
- }
2262
- },
2263
- {
2264
- scope: ["strong", "markup.heading.markdown", "markup.bold.markdown"],
2265
- settings: {
2266
- fontStyle: "bold"
2267
- }
2268
- },
2269
- {
2270
- scope: ["markup.italic.markdown"],
2271
- settings: {
2272
- fontStyle: "italic"
2273
- }
2274
- },
2275
- {
2276
- scope: "meta.link.inline.markdown",
2277
- settings: {
2278
- fontStyle: "underline",
2279
- foreground: variable("token-link")
2280
- }
2281
- },
2282
- {
2283
- scope: ["string", "markup.fenced_code", "markup.inline"],
2284
- settings: {
2285
- foreground: variable("token-string")
2286
- }
2287
- },
2288
- {
2289
- scope: ["comment", "string.quoted.docstring.multi"],
2290
- settings: {
2291
- foreground: variable("token-comment")
2292
- }
2293
- },
2294
- {
2295
- scope: [
2296
- "constant.numeric",
2297
- "constant.language",
2298
- "constant.other.placeholder",
2299
- "constant.character.format.placeholder",
2300
- "variable.language.this",
2301
- "variable.other.object",
2302
- "variable.other.class",
2303
- "variable.other.constant",
2304
- "meta.property-name",
2305
- "meta.property-value",
2306
- "support"
2307
- ],
2308
- settings: {
2309
- foreground: variable("token-constant")
2310
- }
2311
- },
2312
- {
2313
- scope: [
2314
- "keyword",
2315
- "storage.modifier",
2316
- "storage.type",
2317
- "storage.control.clojure",
2318
- "entity.name.function.clojure",
2319
- "entity.name.tag.yaml",
2320
- "support.function.node",
2321
- "support.type.property-name.json",
2322
- "punctuation.separator.key-value",
2323
- "punctuation.definition.template-expression"
2324
- ],
2325
- settings: {
2326
- foreground: variable("token-keyword")
2327
- }
2328
- },
2329
- {
2330
- scope: "variable.parameter.function",
2331
- settings: {
2332
- foreground: variable("token-parameter")
2333
- }
2334
- },
2335
- {
2336
- scope: [
2337
- "support.function",
2338
- "entity.name.type",
2339
- "entity.other.inherited-class",
2340
- "meta.function-call",
2341
- "meta.instance.constructor",
2342
- "entity.other.attribute-name",
2343
- "entity.name.function",
2344
- "constant.keyword.clojure"
2345
- ],
2346
- settings: {
2347
- foreground: variable("token-function")
2348
- }
2349
- },
2350
- {
2351
- scope: [
2352
- "entity.name.tag",
2353
- "string.quoted",
2354
- "string.regexp",
2355
- "string.interpolated",
2356
- "string.template",
2357
- "string.unquoted.plain.out.yaml",
2358
- "keyword.other.template"
2359
- ],
2360
- settings: {
2361
- foreground: variable("token-string-expression")
2362
- }
2363
- },
2364
- {
2365
- scope: [
2366
- "punctuation.definition.arguments",
2367
- "punctuation.definition.dict",
2368
- "punctuation.separator",
2369
- "meta.function-call.arguments"
2370
- ],
2371
- settings: {
2372
- foreground: variable("token-punctuation")
2373
- }
2374
- },
2375
- {
2376
- // [Custom] Markdown links
2377
- scope: [
2378
- "markup.underline.link",
2379
- "punctuation.definition.metadata.markdown"
2380
- ],
2381
- settings: {
2382
- foreground: variable("token-link")
2383
- }
2384
- },
2385
- {
2386
- // [Custom] Markdown list
2387
- scope: ["beginning.punctuation.definition.list.markdown"],
2388
- settings: {
2389
- foreground: variable("token-string")
2390
- }
2391
- },
2392
- {
2393
- // [Custom] Markdown punctuation definition brackets
2394
- scope: [
2395
- "punctuation.definition.string.begin.markdown",
2396
- "punctuation.definition.string.end.markdown",
2397
- "string.other.link.title.markdown",
2398
- "string.other.link.description.markdown"
2399
- ],
2400
- settings: {
2401
- foreground: variable("token-keyword")
2402
- }
2403
- },
2404
- {
2405
- // [Custom] Diff
2406
- scope: [
2407
- "markup.inserted",
2408
- "meta.diff.header.to-file",
2409
- "punctuation.definition.inserted"
2410
- ],
2411
- settings: {
2412
- foreground: variable("token-inserted")
2413
- }
2414
- },
2415
- {
2416
- scope: [
2417
- "markup.deleted",
2418
- "meta.diff.header.from-file",
2419
- "punctuation.definition.deleted"
2420
- ],
2421
- settings: {
2422
- foreground: variable("token-deleted")
2423
- }
2424
- },
2425
- {
2426
- scope: [
2427
- "markup.changed",
2428
- "punctuation.definition.changed"
2429
- ],
2430
- settings: {
2431
- foreground: variable("token-changed")
2432
- }
2433
- }
2434
- ]
2435
- };
2436
- if (!fontStyle) {
2437
- theme.tokenColors = theme.tokenColors?.map((tokenColor) => {
2438
- if (tokenColor.settings?.fontStyle)
2439
- delete tokenColor.settings.fontStyle;
2440
- return tokenColor;
2441
- });
2442
- }
2443
- return theme;
1228
+ const { name = "css-variables", variablePrefix = "--shiki-", fontStyle = true } = options;
1229
+ const variable = (name) => {
1230
+ if (options.variableDefaults?.[name]) return `var(${variablePrefix}${name}, ${options.variableDefaults[name]})`;
1231
+ return `var(${variablePrefix}${name})`;
1232
+ };
1233
+ const theme = {
1234
+ name,
1235
+ type: "dark",
1236
+ colors: {
1237
+ "editor.foreground": variable("foreground"),
1238
+ "editor.background": variable("background"),
1239
+ "terminal.ansiBlack": variable("ansi-black"),
1240
+ "terminal.ansiRed": variable("ansi-red"),
1241
+ "terminal.ansiGreen": variable("ansi-green"),
1242
+ "terminal.ansiYellow": variable("ansi-yellow"),
1243
+ "terminal.ansiBlue": variable("ansi-blue"),
1244
+ "terminal.ansiMagenta": variable("ansi-magenta"),
1245
+ "terminal.ansiCyan": variable("ansi-cyan"),
1246
+ "terminal.ansiWhite": variable("ansi-white"),
1247
+ "terminal.ansiBrightBlack": variable("ansi-bright-black"),
1248
+ "terminal.ansiBrightRed": variable("ansi-bright-red"),
1249
+ "terminal.ansiBrightGreen": variable("ansi-bright-green"),
1250
+ "terminal.ansiBrightYellow": variable("ansi-bright-yellow"),
1251
+ "terminal.ansiBrightBlue": variable("ansi-bright-blue"),
1252
+ "terminal.ansiBrightMagenta": variable("ansi-bright-magenta"),
1253
+ "terminal.ansiBrightCyan": variable("ansi-bright-cyan"),
1254
+ "terminal.ansiBrightWhite": variable("ansi-bright-white")
1255
+ },
1256
+ tokenColors: [
1257
+ {
1258
+ scope: [
1259
+ "keyword.operator.accessor",
1260
+ "meta.group.braces.round.function.arguments",
1261
+ "meta.template.expression",
1262
+ "markup.fenced_code meta.embedded.block"
1263
+ ],
1264
+ settings: { foreground: variable("foreground") }
1265
+ },
1266
+ {
1267
+ scope: "emphasis",
1268
+ settings: { fontStyle: "italic" }
1269
+ },
1270
+ {
1271
+ scope: [
1272
+ "strong",
1273
+ "markup.heading.markdown",
1274
+ "markup.bold.markdown"
1275
+ ],
1276
+ settings: { fontStyle: "bold" }
1277
+ },
1278
+ {
1279
+ scope: ["markup.italic.markdown"],
1280
+ settings: { fontStyle: "italic" }
1281
+ },
1282
+ {
1283
+ scope: "meta.link.inline.markdown",
1284
+ settings: {
1285
+ fontStyle: "underline",
1286
+ foreground: variable("token-link")
1287
+ }
1288
+ },
1289
+ {
1290
+ scope: [
1291
+ "string",
1292
+ "markup.fenced_code",
1293
+ "markup.inline"
1294
+ ],
1295
+ settings: { foreground: variable("token-string") }
1296
+ },
1297
+ {
1298
+ scope: ["comment", "string.quoted.docstring.multi"],
1299
+ settings: { foreground: variable("token-comment") }
1300
+ },
1301
+ {
1302
+ scope: [
1303
+ "constant.numeric",
1304
+ "constant.language",
1305
+ "constant.other.placeholder",
1306
+ "constant.character.format.placeholder",
1307
+ "variable.language.this",
1308
+ "variable.other.object",
1309
+ "variable.other.class",
1310
+ "variable.other.constant",
1311
+ "meta.property-name",
1312
+ "meta.property-value",
1313
+ "support"
1314
+ ],
1315
+ settings: { foreground: variable("token-constant") }
1316
+ },
1317
+ {
1318
+ scope: [
1319
+ "keyword",
1320
+ "storage.modifier",
1321
+ "storage.type",
1322
+ "storage.control.clojure",
1323
+ "entity.name.function.clojure",
1324
+ "entity.name.tag.yaml",
1325
+ "support.function.node",
1326
+ "support.type.property-name.json",
1327
+ "punctuation.separator.key-value",
1328
+ "punctuation.definition.template-expression"
1329
+ ],
1330
+ settings: { foreground: variable("token-keyword") }
1331
+ },
1332
+ {
1333
+ scope: "variable.parameter.function",
1334
+ settings: { foreground: variable("token-parameter") }
1335
+ },
1336
+ {
1337
+ scope: [
1338
+ "support.function",
1339
+ "entity.name.type",
1340
+ "entity.other.inherited-class",
1341
+ "meta.function-call",
1342
+ "meta.instance.constructor",
1343
+ "entity.other.attribute-name",
1344
+ "entity.name.function",
1345
+ "constant.keyword.clojure"
1346
+ ],
1347
+ settings: { foreground: variable("token-function") }
1348
+ },
1349
+ {
1350
+ scope: [
1351
+ "entity.name.tag",
1352
+ "string.quoted",
1353
+ "string.regexp",
1354
+ "string.interpolated",
1355
+ "string.template",
1356
+ "string.unquoted.plain.out.yaml",
1357
+ "keyword.other.template"
1358
+ ],
1359
+ settings: { foreground: variable("token-string-expression") }
1360
+ },
1361
+ {
1362
+ scope: [
1363
+ "punctuation.definition.arguments",
1364
+ "punctuation.definition.dict",
1365
+ "punctuation.separator",
1366
+ "meta.function-call.arguments"
1367
+ ],
1368
+ settings: { foreground: variable("token-punctuation") }
1369
+ },
1370
+ {
1371
+ scope: ["markup.underline.link", "punctuation.definition.metadata.markdown"],
1372
+ settings: { foreground: variable("token-link") }
1373
+ },
1374
+ {
1375
+ scope: ["beginning.punctuation.definition.list.markdown"],
1376
+ settings: { foreground: variable("token-string") }
1377
+ },
1378
+ {
1379
+ scope: [
1380
+ "punctuation.definition.string.begin.markdown",
1381
+ "punctuation.definition.string.end.markdown",
1382
+ "string.other.link.title.markdown",
1383
+ "string.other.link.description.markdown"
1384
+ ],
1385
+ settings: { foreground: variable("token-keyword") }
1386
+ },
1387
+ {
1388
+ scope: [
1389
+ "markup.inserted",
1390
+ "meta.diff.header.to-file",
1391
+ "punctuation.definition.inserted"
1392
+ ],
1393
+ settings: { foreground: variable("token-inserted") }
1394
+ },
1395
+ {
1396
+ scope: [
1397
+ "markup.deleted",
1398
+ "meta.diff.header.from-file",
1399
+ "punctuation.definition.deleted"
1400
+ ],
1401
+ settings: { foreground: variable("token-deleted") }
1402
+ },
1403
+ {
1404
+ scope: ["markup.changed", "punctuation.definition.changed"],
1405
+ settings: { foreground: variable("token-changed") }
1406
+ }
1407
+ ]
1408
+ };
1409
+ if (!fontStyle) theme.tokenColors = theme.tokenColors?.map((tokenColor) => {
1410
+ if (tokenColor.settings?.fontStyle) delete tokenColor.settings.fontStyle;
1411
+ return tokenColor;
1412
+ });
1413
+ return theme;
2444
1414
  }
2445
1415
 
2446
- export { addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createBundledHighlighter, createCssVariablesTheme, createHighlighterCore, createHighlighterCoreSync, createPositionConverter, createShikiInternal, createShikiInternalSync, createSingletonShorthands, createdBundledHighlighter, enableDeprecationWarnings, flatTokenVariants, getSingletonHighlighterCore, getTokenStyleObject, guessEmbeddedLanguages, hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations, warnDeprecated };
1416
+ //#endregion
1417
+ export { ShikiError, addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createBundledHighlighter, createCssVariablesTheme, createHighlighterCore, createHighlighterCoreSync, createPositionConverter, createShikiInternal, createShikiInternalSync, createShikiPrimitive, createShikiPrimitiveAsync, createSingletonShorthands, flatTokenVariants, getLastGrammarState, getSingletonHighlighterCore, getTokenStyleObject, guessEmbeddedLanguages, hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations };