@shikijs/transformers 1.16.1 → 1.16.3

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 CHANGED
@@ -1,55 +1,48 @@
1
1
  import { ShikiTransformer, ShikiTransformerContext } from 'shiki';
2
2
  import { Element } from 'hast';
3
3
 
4
- interface TransformerRenderWhitespaceOptions {
4
+ interface TransformerCompactLineOption {
5
5
  /**
6
- * Class for tab
7
- *
8
- * @default 'tab'
6
+ * 1-based line number.
9
7
  */
10
- classTab?: string;
8
+ line: number;
9
+ classes?: string[];
10
+ }
11
+ /**
12
+ * Transformer for `shiki`'s legacy `lineOptions`
13
+ */
14
+ declare function transformerCompactLineOptions(lineOptions?: TransformerCompactLineOption[]): ShikiTransformer;
15
+
16
+ interface TransformerNotationDiffOptions {
11
17
  /**
12
- * Class for space
13
- *
14
- * @default 'space'
18
+ * Class for added lines
15
19
  */
16
- classSpace?: string;
20
+ classLineAdd?: string;
17
21
  /**
18
- * Position of rendered whitespace
19
- * @default all position
22
+ * Class for removed lines
20
23
  */
21
- position?: 'all' | 'boundary' | 'trailing';
24
+ classLineRemove?: string;
25
+ /**
26
+ * Class added to the <pre> element when the current code has diff
27
+ */
28
+ classActivePre?: string;
22
29
  }
23
30
  /**
24
- * Render whitespaces as separate tokens.
25
- * Apply with CSS, it can be used to render tabs and spaces visually.
26
- */
27
- declare function transformerRenderWhitespace(options?: TransformerRenderWhitespaceOptions): ShikiTransformer;
28
-
29
- /**
30
- * Remove line breaks between lines.
31
- * Useful when you override `display: block` to `.line` in CSS.
32
- */
33
- declare function transformerRemoveLineBreak(): ShikiTransformer;
34
-
35
- /**
36
- * Remove notation escapes.
37
- * Useful when you want to write `// [!code` in markdown.
38
- * If you process `// [\!code ...]` expression, you can get `// [!code ...]` in the output.
31
+ * Use `[!code ++]` and `[!code --]` to mark added and removed lines.
39
32
  */
40
- declare function transformerRemoveNotationEscape(): ShikiTransformer;
33
+ declare function transformerNotationDiff(options?: TransformerNotationDiffOptions): ShikiTransformer;
41
34
 
42
- interface TransformerCompactLineOption {
35
+ interface TransformerNotationErrorLevelOptions {
36
+ classMap?: Record<string, string | string[]>;
43
37
  /**
44
- * 1-based line number.
38
+ * Class added to the <pre> element when the current code has diff
45
39
  */
46
- line: number;
47
- classes?: string[];
40
+ classActivePre?: string;
48
41
  }
49
42
  /**
50
- * Transformer for `shiki`'s legacy `lineOptions`
43
+ * Allow using `[!code error]` `[!code warning]` notation in code to mark highlighted lines.
51
44
  */
52
- declare function transformerCompactLineOptions(lineOptions?: TransformerCompactLineOption[]): ShikiTransformer;
45
+ declare function transformerNotationErrorLevel(options?: TransformerNotationErrorLevelOptions): ShikiTransformer;
53
46
 
54
47
  interface TransformerNotationFocusOptions {
55
48
  /**
@@ -93,50 +86,43 @@ interface TransformerNotationWordHighlightOptions {
93
86
  }
94
87
  declare function transformerNotationWordHighlight(options?: TransformerNotationWordHighlightOptions): ShikiTransformer;
95
88
 
96
- declare function parseMetaHighlightWords(meta: string): string[];
97
- interface TransformerMetaWordHighlightOptions {
98
- /**
99
- * Class for highlighted words
100
- *
101
- * @default 'highlighted-word'
102
- */
103
- className?: string;
104
- }
105
89
  /**
106
- * Allow using `/word/` in the code snippet meta to mark highlighted words.
90
+ * Remove line breaks between lines.
91
+ * Useful when you override `display: block` to `.line` in CSS.
107
92
  */
108
- declare function transformerMetaWordHighlight(options?: TransformerMetaWordHighlightOptions): ShikiTransformer;
93
+ declare function transformerRemoveLineBreak(): ShikiTransformer;
109
94
 
110
- interface TransformerNotationDiffOptions {
111
- /**
112
- * Class for added lines
113
- */
114
- classLineAdd?: string;
95
+ /**
96
+ * Remove notation escapes.
97
+ * Useful when you want to write `// [!code` in markdown.
98
+ * If you process `// [\!code ...]` expression, you can get `// [!code ...]` in the output.
99
+ */
100
+ declare function transformerRemoveNotationEscape(): ShikiTransformer;
101
+
102
+ interface TransformerRenderWhitespaceOptions {
115
103
  /**
116
- * Class for removed lines
104
+ * Class for tab
105
+ *
106
+ * @default 'tab'
117
107
  */
118
- classLineRemove?: string;
108
+ classTab?: string;
119
109
  /**
120
- * Class added to the <pre> element when the current code has diff
110
+ * Class for space
111
+ *
112
+ * @default 'space'
121
113
  */
122
- classActivePre?: string;
123
- }
124
- /**
125
- * Use `[!code ++]` and `[!code --]` to mark added and removed lines.
126
- */
127
- declare function transformerNotationDiff(options?: TransformerNotationDiffOptions): ShikiTransformer;
128
-
129
- interface TransformerNotationErrorLevelOptions {
130
- classMap?: Record<string, string | string[]>;
114
+ classSpace?: string;
131
115
  /**
132
- * Class added to the <pre> element when the current code has diff
116
+ * Position of rendered whitespace
117
+ * @default all position
133
118
  */
134
- classActivePre?: string;
119
+ position?: 'all' | 'boundary' | 'trailing';
135
120
  }
136
121
  /**
137
- * Allow using `[!code error]` `[!code warning]` notation in code to mark highlighted lines.
122
+ * Render whitespaces as separate tokens.
123
+ * Apply with CSS, it can be used to render tabs and spaces visually.
138
124
  */
139
- declare function transformerNotationErrorLevel(options?: TransformerNotationErrorLevelOptions): ShikiTransformer;
125
+ declare function transformerRenderWhitespace(options?: TransformerRenderWhitespaceOptions): ShikiTransformer;
140
126
 
141
127
  declare function parseMetaHighlightString(meta: string): number[] | null;
142
128
  interface TransformerMetaHighlightOptions {
@@ -152,6 +138,20 @@ interface TransformerMetaHighlightOptions {
152
138
  */
153
139
  declare function transformerMetaHighlight(options?: TransformerMetaHighlightOptions): ShikiTransformer;
154
140
 
141
+ declare function parseMetaHighlightWords(meta: string): string[];
142
+ interface TransformerMetaWordHighlightOptions {
143
+ /**
144
+ * Class for highlighted words
145
+ *
146
+ * @default 'highlighted-word'
147
+ */
148
+ className?: string;
149
+ }
150
+ /**
151
+ * Allow using `/word/` in the code snippet meta to mark highlighted words.
152
+ */
153
+ declare function transformerMetaWordHighlight(options?: TransformerMetaWordHighlightOptions): ShikiTransformer;
154
+
155
155
  declare function createCommentNotationTransformer(name: string, regex: RegExp, onMatch: (this: ShikiTransformerContext, match: string[], line: Element, commentNode: Element, lines: Element[], index: number) => boolean, removeEmptyLines?: boolean): ShikiTransformer;
156
156
 
157
157
  export { type TransformerCompactLineOption, type TransformerMetaHighlightOptions, type TransformerMetaWordHighlightOptions, type TransformerNotationDiffOptions, type TransformerNotationErrorLevelOptions, type TransformerNotationFocusOptions, type TransformerNotationHighlightOptions, type TransformerNotationWordHighlightOptions, type TransformerRenderWhitespaceOptions, createCommentNotationTransformer, parseMetaHighlightString, parseMetaHighlightWords, transformerCompactLineOptions, transformerMetaHighlight, transformerMetaWordHighlight, transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationWordHighlight, transformerRemoveLineBreak, transformerRemoveNotationEscape, transformerRenderWhitespace };
package/dist/index.d.ts CHANGED
@@ -1,55 +1,48 @@
1
1
  import { ShikiTransformer, ShikiTransformerContext } from 'shiki';
2
2
  import { Element } from 'hast';
3
3
 
4
- interface TransformerRenderWhitespaceOptions {
4
+ interface TransformerCompactLineOption {
5
5
  /**
6
- * Class for tab
7
- *
8
- * @default 'tab'
6
+ * 1-based line number.
9
7
  */
10
- classTab?: string;
8
+ line: number;
9
+ classes?: string[];
10
+ }
11
+ /**
12
+ * Transformer for `shiki`'s legacy `lineOptions`
13
+ */
14
+ declare function transformerCompactLineOptions(lineOptions?: TransformerCompactLineOption[]): ShikiTransformer;
15
+
16
+ interface TransformerNotationDiffOptions {
11
17
  /**
12
- * Class for space
13
- *
14
- * @default 'space'
18
+ * Class for added lines
15
19
  */
16
- classSpace?: string;
20
+ classLineAdd?: string;
17
21
  /**
18
- * Position of rendered whitespace
19
- * @default all position
22
+ * Class for removed lines
20
23
  */
21
- position?: 'all' | 'boundary' | 'trailing';
24
+ classLineRemove?: string;
25
+ /**
26
+ * Class added to the <pre> element when the current code has diff
27
+ */
28
+ classActivePre?: string;
22
29
  }
23
30
  /**
24
- * Render whitespaces as separate tokens.
25
- * Apply with CSS, it can be used to render tabs and spaces visually.
26
- */
27
- declare function transformerRenderWhitespace(options?: TransformerRenderWhitespaceOptions): ShikiTransformer;
28
-
29
- /**
30
- * Remove line breaks between lines.
31
- * Useful when you override `display: block` to `.line` in CSS.
32
- */
33
- declare function transformerRemoveLineBreak(): ShikiTransformer;
34
-
35
- /**
36
- * Remove notation escapes.
37
- * Useful when you want to write `// [!code` in markdown.
38
- * If you process `// [\!code ...]` expression, you can get `// [!code ...]` in the output.
31
+ * Use `[!code ++]` and `[!code --]` to mark added and removed lines.
39
32
  */
40
- declare function transformerRemoveNotationEscape(): ShikiTransformer;
33
+ declare function transformerNotationDiff(options?: TransformerNotationDiffOptions): ShikiTransformer;
41
34
 
42
- interface TransformerCompactLineOption {
35
+ interface TransformerNotationErrorLevelOptions {
36
+ classMap?: Record<string, string | string[]>;
43
37
  /**
44
- * 1-based line number.
38
+ * Class added to the <pre> element when the current code has diff
45
39
  */
46
- line: number;
47
- classes?: string[];
40
+ classActivePre?: string;
48
41
  }
49
42
  /**
50
- * Transformer for `shiki`'s legacy `lineOptions`
43
+ * Allow using `[!code error]` `[!code warning]` notation in code to mark highlighted lines.
51
44
  */
52
- declare function transformerCompactLineOptions(lineOptions?: TransformerCompactLineOption[]): ShikiTransformer;
45
+ declare function transformerNotationErrorLevel(options?: TransformerNotationErrorLevelOptions): ShikiTransformer;
53
46
 
54
47
  interface TransformerNotationFocusOptions {
55
48
  /**
@@ -93,50 +86,43 @@ interface TransformerNotationWordHighlightOptions {
93
86
  }
94
87
  declare function transformerNotationWordHighlight(options?: TransformerNotationWordHighlightOptions): ShikiTransformer;
95
88
 
96
- declare function parseMetaHighlightWords(meta: string): string[];
97
- interface TransformerMetaWordHighlightOptions {
98
- /**
99
- * Class for highlighted words
100
- *
101
- * @default 'highlighted-word'
102
- */
103
- className?: string;
104
- }
105
89
  /**
106
- * Allow using `/word/` in the code snippet meta to mark highlighted words.
90
+ * Remove line breaks between lines.
91
+ * Useful when you override `display: block` to `.line` in CSS.
107
92
  */
108
- declare function transformerMetaWordHighlight(options?: TransformerMetaWordHighlightOptions): ShikiTransformer;
93
+ declare function transformerRemoveLineBreak(): ShikiTransformer;
109
94
 
110
- interface TransformerNotationDiffOptions {
111
- /**
112
- * Class for added lines
113
- */
114
- classLineAdd?: string;
95
+ /**
96
+ * Remove notation escapes.
97
+ * Useful when you want to write `// [!code` in markdown.
98
+ * If you process `// [\!code ...]` expression, you can get `// [!code ...]` in the output.
99
+ */
100
+ declare function transformerRemoveNotationEscape(): ShikiTransformer;
101
+
102
+ interface TransformerRenderWhitespaceOptions {
115
103
  /**
116
- * Class for removed lines
104
+ * Class for tab
105
+ *
106
+ * @default 'tab'
117
107
  */
118
- classLineRemove?: string;
108
+ classTab?: string;
119
109
  /**
120
- * Class added to the <pre> element when the current code has diff
110
+ * Class for space
111
+ *
112
+ * @default 'space'
121
113
  */
122
- classActivePre?: string;
123
- }
124
- /**
125
- * Use `[!code ++]` and `[!code --]` to mark added and removed lines.
126
- */
127
- declare function transformerNotationDiff(options?: TransformerNotationDiffOptions): ShikiTransformer;
128
-
129
- interface TransformerNotationErrorLevelOptions {
130
- classMap?: Record<string, string | string[]>;
114
+ classSpace?: string;
131
115
  /**
132
- * Class added to the <pre> element when the current code has diff
116
+ * Position of rendered whitespace
117
+ * @default all position
133
118
  */
134
- classActivePre?: string;
119
+ position?: 'all' | 'boundary' | 'trailing';
135
120
  }
136
121
  /**
137
- * Allow using `[!code error]` `[!code warning]` notation in code to mark highlighted lines.
122
+ * Render whitespaces as separate tokens.
123
+ * Apply with CSS, it can be used to render tabs and spaces visually.
138
124
  */
139
- declare function transformerNotationErrorLevel(options?: TransformerNotationErrorLevelOptions): ShikiTransformer;
125
+ declare function transformerRenderWhitespace(options?: TransformerRenderWhitespaceOptions): ShikiTransformer;
140
126
 
141
127
  declare function parseMetaHighlightString(meta: string): number[] | null;
142
128
  interface TransformerMetaHighlightOptions {
@@ -152,6 +138,20 @@ interface TransformerMetaHighlightOptions {
152
138
  */
153
139
  declare function transformerMetaHighlight(options?: TransformerMetaHighlightOptions): ShikiTransformer;
154
140
 
141
+ declare function parseMetaHighlightWords(meta: string): string[];
142
+ interface TransformerMetaWordHighlightOptions {
143
+ /**
144
+ * Class for highlighted words
145
+ *
146
+ * @default 'highlighted-word'
147
+ */
148
+ className?: string;
149
+ }
150
+ /**
151
+ * Allow using `/word/` in the code snippet meta to mark highlighted words.
152
+ */
153
+ declare function transformerMetaWordHighlight(options?: TransformerMetaWordHighlightOptions): ShikiTransformer;
154
+
155
155
  declare function createCommentNotationTransformer(name: string, regex: RegExp, onMatch: (this: ShikiTransformerContext, match: string[], line: Element, commentNode: Element, lines: Element[], index: number) => boolean, removeEmptyLines?: boolean): ShikiTransformer;
156
156
 
157
157
  export { type TransformerCompactLineOption, type TransformerMetaHighlightOptions, type TransformerMetaWordHighlightOptions, type TransformerNotationDiffOptions, type TransformerNotationErrorLevelOptions, type TransformerNotationFocusOptions, type TransformerNotationHighlightOptions, type TransformerNotationWordHighlightOptions, type TransformerRenderWhitespaceOptions, createCommentNotationTransformer, parseMetaHighlightString, parseMetaHighlightWords, transformerCompactLineOptions, transformerMetaHighlight, transformerMetaWordHighlight, transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationWordHighlight, transformerRemoveLineBreak, transformerRemoveNotationEscape, transformerRenderWhitespace };
package/dist/index.mjs CHANGED
@@ -1,134 +1,3 @@
1
- function separateContinuousSpaces(inputs) {
2
- const result = [];
3
- let current = "";
4
- function bump() {
5
- if (current.length)
6
- result.push(current);
7
- current = "";
8
- }
9
- inputs.forEach((part, idx) => {
10
- if (isTab(part)) {
11
- bump();
12
- result.push(part);
13
- } else if (isSpace(part) && (isSpace(inputs[idx - 1]) || isSpace(inputs[idx + 1]))) {
14
- bump();
15
- result.push(part);
16
- } else {
17
- current += part;
18
- }
19
- });
20
- bump();
21
- return result;
22
- }
23
- function isTab(part) {
24
- return part === " ";
25
- }
26
- function isSpace(part) {
27
- return part === " " || part === " ";
28
- }
29
- function splitSpaces(parts, type, renderContinuousSpaces = true) {
30
- if (type === "all")
31
- return parts;
32
- let leftCount = 0;
33
- let rightCount = 0;
34
- if (type === "boundary") {
35
- for (let i = 0; i < parts.length; i++) {
36
- if (isSpace(parts[i]))
37
- leftCount++;
38
- else
39
- break;
40
- }
41
- }
42
- if (type === "boundary" || type === "trailing") {
43
- for (let i = parts.length - 1; i >= 0; i--) {
44
- if (isSpace(parts[i]))
45
- rightCount++;
46
- else
47
- break;
48
- }
49
- }
50
- const middle = parts.slice(leftCount, parts.length - rightCount);
51
- return [
52
- ...parts.slice(0, leftCount),
53
- ...renderContinuousSpaces ? separateContinuousSpaces(middle) : [middle.join("")],
54
- ...parts.slice(parts.length - rightCount)
55
- ];
56
- }
57
-
58
- function transformerRenderWhitespace(options = {}) {
59
- const classMap = {
60
- " ": options.classSpace ?? "space",
61
- " ": options.classTab ?? "tab"
62
- };
63
- const position = options.position ?? "all";
64
- const keys = Object.keys(classMap);
65
- return {
66
- name: "@shikijs/transformers:render-whitespace",
67
- // We use `root` hook here to ensure it runs after all other transformers
68
- root(root) {
69
- const pre = root.children[0];
70
- const code = pre.children[0];
71
- code.children.forEach(
72
- (line) => {
73
- if (line.type !== "element")
74
- return;
75
- const elements = line.children.filter((token) => token.type === "element");
76
- const last = elements.length - 1;
77
- line.children = line.children.flatMap((token) => {
78
- if (token.type !== "element")
79
- return token;
80
- const index = elements.indexOf(token);
81
- if (position === "boundary" && index !== 0 && index !== last)
82
- return token;
83
- if (position === "trailing" && index !== last)
84
- return token;
85
- const node = token.children[0];
86
- if (node.type !== "text" || !node.value)
87
- return token;
88
- const parts = splitSpaces(
89
- node.value.split(/([ \t])/).filter((i) => i.length),
90
- position === "boundary" && index === last && last !== 0 ? "trailing" : position,
91
- position !== "trailing"
92
- );
93
- if (parts.length <= 1)
94
- return token;
95
- return parts.map((part) => {
96
- const clone = {
97
- ...token,
98
- properties: { ...token.properties }
99
- };
100
- clone.children = [{ type: "text", value: part }];
101
- if (keys.includes(part)) {
102
- this.addClassToHast(clone, classMap[part]);
103
- delete clone.properties.style;
104
- }
105
- return clone;
106
- });
107
- });
108
- }
109
- );
110
- }
111
- };
112
- }
113
-
114
- function transformerRemoveLineBreak() {
115
- return {
116
- name: "@shikijs/transformers:remove-line-break",
117
- code(code) {
118
- code.children = code.children.filter((line) => !(line.type === "text" && line.value === "\n"));
119
- }
120
- };
121
- }
122
-
123
- function transformerRemoveNotationEscape() {
124
- return {
125
- name: "@shikijs/transformers:remove-notation-escape",
126
- postprocess(code) {
127
- return code.replace(/\[\\!code/g, "[!code");
128
- }
129
- };
130
- }
131
-
132
1
  function transformerCompactLineOptions(lineOptions = []) {
133
2
  return {
134
3
  name: "@shikijs/transformers:compact-line-options",
@@ -207,6 +76,41 @@ function transformerNotationMap(options = {}, name = "@shikijs/transformers:nota
207
76
  );
208
77
  }
209
78
 
79
+ function transformerNotationDiff(options = {}) {
80
+ const {
81
+ classLineAdd = "diff add",
82
+ classLineRemove = "diff remove",
83
+ classActivePre = "has-diff"
84
+ } = options;
85
+ return transformerNotationMap(
86
+ {
87
+ classMap: {
88
+ "++": classLineAdd,
89
+ "--": classLineRemove
90
+ },
91
+ classActivePre
92
+ },
93
+ "@shikijs/transformers:notation-diff"
94
+ );
95
+ }
96
+
97
+ function transformerNotationErrorLevel(options = {}) {
98
+ const {
99
+ classMap = {
100
+ error: ["highlighted", "error"],
101
+ warning: ["highlighted", "warning"]
102
+ },
103
+ classActivePre = "has-highlighted"
104
+ } = options;
105
+ return transformerNotationMap(
106
+ {
107
+ classMap,
108
+ classActivePre
109
+ },
110
+ "@shikijs/transformers:notation-error-level"
111
+ );
112
+ }
113
+
210
114
  function transformerNotationFocus(options = {}) {
211
115
  const {
212
116
  classActiveLine = "focused",
@@ -329,79 +233,135 @@ function transformerNotationWordHighlight(options = {}) {
329
233
  );
330
234
  }
331
235
 
332
- function parseMetaHighlightWords(meta) {
333
- if (!meta)
334
- return [];
335
- const match = Array.from(meta.matchAll(/\/((?:\\.|[^/])+)\//g));
336
- return match.map((v) => v[1].replace(/\\(.)/g, "$1"));
337
- }
338
- function transformerMetaWordHighlight(options = {}) {
339
- const {
340
- className = "highlighted-word"
341
- } = options;
236
+ function transformerRemoveLineBreak() {
342
237
  return {
343
- name: "@shikijs/transformers:meta-word-highlight",
344
- preprocess(code, options2) {
345
- if (!this.options.meta?.__raw)
346
- return;
347
- const words = parseMetaHighlightWords(this.options.meta.__raw);
348
- options2.decorations || (options2.decorations = []);
349
- for (const word of words) {
350
- const indexes = findAllSubstringIndexes(code, word);
351
- for (const index of indexes) {
352
- options2.decorations.push({
353
- start: index,
354
- end: index + word.length,
355
- properties: {
356
- class: className
357
- }
358
- });
359
- }
360
- }
238
+ name: "@shikijs/transformers:remove-line-break",
239
+ code(code) {
240
+ code.children = code.children.filter((line) => !(line.type === "text" && line.value === "\n"));
361
241
  }
362
242
  };
363
243
  }
364
- function findAllSubstringIndexes(str, substr) {
365
- const indexes = [];
366
- let i = -1;
367
- while ((i = str.indexOf(substr, i + 1)) !== -1)
368
- indexes.push(i);
369
- return indexes;
244
+
245
+ function transformerRemoveNotationEscape() {
246
+ return {
247
+ name: "@shikijs/transformers:remove-notation-escape",
248
+ postprocess(code) {
249
+ return code.replace(/\[\\!code/g, "[!code");
250
+ }
251
+ };
370
252
  }
371
253
 
372
- function transformerNotationDiff(options = {}) {
373
- const {
374
- classLineAdd = "diff add",
375
- classLineRemove = "diff remove",
376
- classActivePre = "has-diff"
377
- } = options;
378
- return transformerNotationMap(
379
- {
380
- classMap: {
381
- "++": classLineAdd,
382
- "--": classLineRemove
383
- },
384
- classActivePre
385
- },
386
- "@shikijs/transformers:notation-diff"
387
- );
254
+ function separateContinuousSpaces(inputs) {
255
+ const result = [];
256
+ let current = "";
257
+ function bump() {
258
+ if (current.length)
259
+ result.push(current);
260
+ current = "";
261
+ }
262
+ inputs.forEach((part, idx) => {
263
+ if (isTab(part)) {
264
+ bump();
265
+ result.push(part);
266
+ } else if (isSpace(part) && (isSpace(inputs[idx - 1]) || isSpace(inputs[idx + 1]))) {
267
+ bump();
268
+ result.push(part);
269
+ } else {
270
+ current += part;
271
+ }
272
+ });
273
+ bump();
274
+ return result;
275
+ }
276
+ function isTab(part) {
277
+ return part === " ";
278
+ }
279
+ function isSpace(part) {
280
+ return part === " " || part === " ";
281
+ }
282
+ function splitSpaces(parts, type, renderContinuousSpaces = true) {
283
+ if (type === "all")
284
+ return parts;
285
+ let leftCount = 0;
286
+ let rightCount = 0;
287
+ if (type === "boundary") {
288
+ for (let i = 0; i < parts.length; i++) {
289
+ if (isSpace(parts[i]))
290
+ leftCount++;
291
+ else
292
+ break;
293
+ }
294
+ }
295
+ if (type === "boundary" || type === "trailing") {
296
+ for (let i = parts.length - 1; i >= 0; i--) {
297
+ if (isSpace(parts[i]))
298
+ rightCount++;
299
+ else
300
+ break;
301
+ }
302
+ }
303
+ const middle = parts.slice(leftCount, parts.length - rightCount);
304
+ return [
305
+ ...parts.slice(0, leftCount),
306
+ ...renderContinuousSpaces ? separateContinuousSpaces(middle) : [middle.join("")],
307
+ ...parts.slice(parts.length - rightCount)
308
+ ];
388
309
  }
389
310
 
390
- function transformerNotationErrorLevel(options = {}) {
391
- const {
392
- classMap = {
393
- error: ["highlighted", "error"],
394
- warning: ["highlighted", "warning"]
395
- },
396
- classActivePre = "has-highlighted"
397
- } = options;
398
- return transformerNotationMap(
399
- {
400
- classMap,
401
- classActivePre
402
- },
403
- "@shikijs/transformers:notation-error-level"
404
- );
311
+ function transformerRenderWhitespace(options = {}) {
312
+ const classMap = {
313
+ " ": options.classSpace ?? "space",
314
+ " ": options.classTab ?? "tab"
315
+ };
316
+ const position = options.position ?? "all";
317
+ const keys = Object.keys(classMap);
318
+ return {
319
+ name: "@shikijs/transformers:render-whitespace",
320
+ // We use `root` hook here to ensure it runs after all other transformers
321
+ root(root) {
322
+ const pre = root.children[0];
323
+ const code = pre.children[0];
324
+ code.children.forEach(
325
+ (line) => {
326
+ if (line.type !== "element")
327
+ return;
328
+ const elements = line.children.filter((token) => token.type === "element");
329
+ const last = elements.length - 1;
330
+ line.children = line.children.flatMap((token) => {
331
+ if (token.type !== "element")
332
+ return token;
333
+ const index = elements.indexOf(token);
334
+ if (position === "boundary" && index !== 0 && index !== last)
335
+ return token;
336
+ if (position === "trailing" && index !== last)
337
+ return token;
338
+ const node = token.children[0];
339
+ if (node.type !== "text" || !node.value)
340
+ return token;
341
+ const parts = splitSpaces(
342
+ node.value.split(/([ \t])/).filter((i) => i.length),
343
+ position === "boundary" && index === last && last !== 0 ? "trailing" : position,
344
+ position !== "trailing"
345
+ );
346
+ if (parts.length <= 1)
347
+ return token;
348
+ return parts.map((part) => {
349
+ const clone = {
350
+ ...token,
351
+ properties: { ...token.properties }
352
+ };
353
+ clone.children = [{ type: "text", value: part }];
354
+ if (keys.includes(part)) {
355
+ this.addClassToHast(clone, classMap[part]);
356
+ delete clone.properties.style;
357
+ }
358
+ return clone;
359
+ });
360
+ });
361
+ }
362
+ );
363
+ }
364
+ };
405
365
  }
406
366
 
407
367
  function parseMetaHighlightString(meta) {
@@ -440,4 +400,44 @@ function transformerMetaHighlight(options = {}) {
440
400
  };
441
401
  }
442
402
 
403
+ function parseMetaHighlightWords(meta) {
404
+ if (!meta)
405
+ return [];
406
+ const match = Array.from(meta.matchAll(/\/((?:\\.|[^/])+)\//g));
407
+ return match.map((v) => v[1].replace(/\\(.)/g, "$1"));
408
+ }
409
+ function transformerMetaWordHighlight(options = {}) {
410
+ const {
411
+ className = "highlighted-word"
412
+ } = options;
413
+ return {
414
+ name: "@shikijs/transformers:meta-word-highlight",
415
+ preprocess(code, options2) {
416
+ if (!this.options.meta?.__raw)
417
+ return;
418
+ const words = parseMetaHighlightWords(this.options.meta.__raw);
419
+ options2.decorations || (options2.decorations = []);
420
+ for (const word of words) {
421
+ const indexes = findAllSubstringIndexes(code, word);
422
+ for (const index of indexes) {
423
+ options2.decorations.push({
424
+ start: index,
425
+ end: index + word.length,
426
+ properties: {
427
+ class: className
428
+ }
429
+ });
430
+ }
431
+ }
432
+ }
433
+ };
434
+ }
435
+ function findAllSubstringIndexes(str, substr) {
436
+ const indexes = [];
437
+ let i = -1;
438
+ while ((i = str.indexOf(substr, i + 1)) !== -1)
439
+ indexes.push(i);
440
+ return indexes;
441
+ }
442
+
443
443
  export { createCommentNotationTransformer, parseMetaHighlightString, parseMetaHighlightWords, transformerCompactLineOptions, transformerMetaHighlight, transformerMetaWordHighlight, transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationWordHighlight, transformerRemoveLineBreak, transformerRemoveNotationEscape, transformerRenderWhitespace };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/transformers",
3
3
  "type": "module",
4
- "version": "1.16.1",
4
+ "version": "1.16.3",
5
5
  "description": "Collective of common transformers transformers for Shiki",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "shiki": "1.16.1"
33
+ "shiki": "1.16.3"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "unbuild",