@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.d.mts +110 -189
- package/dist/index.mjs +1323 -2352
- package/dist/textmate.d.mts +1 -1
- package/dist/textmate.mjs +3 -1
- package/dist/types.d.mts +1 -2
- package/dist/types.mjs +3 -1
- package/package.json +8 -4
package/dist/index.mjs
CHANGED
|
@@ -1,2446 +1,1417 @@
|
|
|
1
|
-
import { ShikiError as ShikiError$1 } from
|
|
2
|
-
|
|
3
|
-
import { FontStyle
|
|
4
|
-
import { toHtml } from
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
235
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
483
|
-
|
|
484
|
-
|
|
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
|
-
|
|
490
|
-
|
|
491
|
-
];
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/highlight/_get-transformers.ts
|
|
341
|
+
const builtInTransformers = [/* @__PURE__ */ transformerDecorations()];
|
|
492
342
|
function getTransformers(options) {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
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
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
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
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
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
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
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
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
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
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
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
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
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
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
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
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
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
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
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
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
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
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
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
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
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
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
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
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
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
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
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
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
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
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
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
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
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
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
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
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
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
|
-
|
|
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 };
|