@shikijs/transformers 4.0.2 → 4.2.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.
Files changed (2) hide show
  1. package/dist/index.mjs +35 -31
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -1,4 +1,7 @@
1
1
  //#region src/shared/parse-comments.ts
2
+ const RE_SPLIT_COMMENT = /(\s+\/\/)/;
3
+ const RE_V1_END_COMMENT_PREFIX = /(?:\/\/|["'#]|;{1,2}|%{1,2}|--)(\s*)$/;
4
+ const RE_V3_END_COMMENT_PREFIX = /(?:\/\/|#|;{1,2}|%{1,2}|--)(\s*)$/;
2
5
  /**
3
6
  * some comment formats have to be located at the end of line
4
7
  * hence we can skip matching them for other tokens
@@ -24,7 +27,7 @@ function parseComments(lines, jsx, matchAlgorithm) {
24
27
  if (token.type !== "text") return element;
25
28
  const isLast = idx === line.children.length - 1;
26
29
  if (!matchToken(token.value, isLast)) return element;
27
- const rawSplits = token.value.split(/(\s+\/\/)/);
30
+ const rawSplits = token.value.split(RE_SPLIT_COMMENT);
28
31
  if (rawSplits.length <= 1) return element;
29
32
  let splits = [rawSplits[0]];
30
33
  for (let i = 1; i < rawSplits.length; i += 2) splits.push(rawSplits[i] + (rawSplits[i + 1] || ""));
@@ -130,15 +133,24 @@ function matchToken(text, isLast) {
130
133
  * For matchAlgorithm v1
131
134
  */
132
135
  function v1ClearEndCommentPrefix(text) {
133
- const match = text.match(/(?:\/\/|["'#]|;{1,2}|%{1,2}|--)(\s*)$/);
136
+ const match = text.match(RE_V1_END_COMMENT_PREFIX);
134
137
  if (match && match[1].trim().length === 0) return text.slice(0, match.index);
135
138
  return text;
136
139
  }
137
-
140
+ /**
141
+ * Remove empty comment prefixes at line end, e.g. `// `
142
+ *
143
+ * For matchAlgorithm v3
144
+ */
145
+ function v3ClearEndCommentPrefix(text) {
146
+ const match = text.match(RE_V3_END_COMMENT_PREFIX);
147
+ if (match && match[1].trim().length === 0) return text.slice(0, match.index).trimEnd();
148
+ return text;
149
+ }
138
150
  //#endregion
139
151
  //#region src/shared/notation-transformer.ts
140
152
  function createCommentNotationTransformer(name, regex, onMatch, matchAlgorithm) {
141
- if (matchAlgorithm == null) matchAlgorithm = "v3";
153
+ matchAlgorithm ??= "v3";
142
154
  return {
143
155
  name,
144
156
  code(code) {
@@ -162,6 +174,7 @@ function createCommentNotationTransformer(name, regex, onMatch, matchAlgorithm)
162
174
  });
163
175
  if (!replaced) continue;
164
176
  if (matchAlgorithm === "v1") comment.info[1] = v1ClearEndCommentPrefix(comment.info[1]);
177
+ else if (matchAlgorithm === "v3") comment.info[1] = v3ClearEndCommentPrefix(comment.info[1]);
165
178
  const isEmpty = comment.info[1].trim().length === 0;
166
179
  if (isEmpty) comment.info[1] = "";
167
180
  if (isEmpty && comment.isLineCommentOnly) linesToRemove.push(comment.line);
@@ -194,7 +207,6 @@ function createCommentNotationTransformer(name, regex, onMatch, matchAlgorithm)
194
207
  }
195
208
  };
196
209
  }
197
-
198
210
  //#endregion
199
211
  //#region src/transformers/compact-line-options.ts
200
212
  /**
@@ -210,12 +222,12 @@ function transformerCompactLineOptions(lineOptions = []) {
210
222
  }
211
223
  };
212
224
  }
213
-
214
225
  //#endregion
215
226
  //#region src/transformers/meta-highlight.ts
227
+ const RE_HIGHLIGHT_LINES = /\{([\d,-]+)\}/;
216
228
  function parseMetaHighlightString(meta) {
217
229
  if (!meta) return null;
218
- const match = meta.match(/\{([\d,-]+)\}/);
230
+ const match = meta.match(RE_HIGHLIGHT_LINES);
219
231
  if (!match) return null;
220
232
  return match[1].split(",").flatMap((v) => {
221
233
  const range = v.split("-").map((n) => Number.parseInt(n, 10));
@@ -241,12 +253,13 @@ function transformerMetaHighlight(options = {}) {
241
253
  }
242
254
  };
243
255
  }
244
-
245
256
  //#endregion
246
257
  //#region src/transformers/meta-highlight-word.ts
258
+ const RE_WORD_MATCH = /\/((?:\\.|[^/])+)\//g;
259
+ const RE_ESCAPE_BACKSLASH = /\\(.)/g;
247
260
  function parseMetaHighlightWords(meta) {
248
261
  if (!meta) return [];
249
- return Array.from(meta.matchAll(/\/((?:\\.|[^/])+)\//g)).map((v) => v[1].replace(/\\(.)/g, "$1"));
262
+ return [...meta.matchAll(RE_WORD_MATCH)].map((v) => v[1].replace(RE_ESCAPE_BACKSLASH, "$1"));
250
263
  }
251
264
  /**
252
265
  * Allow using `/word/` in the code snippet meta to mark highlighted words.
@@ -282,11 +295,11 @@ function findAllSubstringIndexes(str, substr) {
282
295
  }
283
296
  return indexes;
284
297
  }
285
-
286
298
  //#endregion
287
299
  //#region src/transformers/notation-map.ts
300
+ const RE_ESCAPE_SPECIAL = /[.*+?^${}()|[\]\\]/g;
288
301
  function escapeRegExp(str) {
289
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
302
+ return str.replace(RE_ESCAPE_SPECIAL, "\\$&");
290
303
  }
291
304
  function transformerNotationMap(options = {}, name = "@shikijs/transformers:notation-map") {
292
305
  const { classMap = {}, classActivePre = void 0, classActiveCode = void 0 } = options;
@@ -298,7 +311,6 @@ function transformerNotationMap(options = {}, name = "@shikijs/transformers:nota
298
311
  return true;
299
312
  }, options.matchAlgorithm);
300
313
  }
301
-
302
314
  //#endregion
303
315
  //#region src/transformers/notation-diff.ts
304
316
  /**
@@ -316,7 +328,6 @@ function transformerNotationDiff(options = {}) {
316
328
  matchAlgorithm: options.matchAlgorithm
317
329
  }, "@shikijs/transformers:notation-diff");
318
330
  }
319
-
320
331
  //#endregion
321
332
  //#region src/transformers/notation-error-level.ts
322
333
  /**
@@ -335,7 +346,6 @@ function transformerNotationErrorLevel(options = {}) {
335
346
  matchAlgorithm: options.matchAlgorithm
336
347
  }, "@shikijs/transformers:notation-error-level");
337
348
  }
338
-
339
349
  //#endregion
340
350
  //#region src/transformers/notation-focus.ts
341
351
  /**
@@ -350,7 +360,6 @@ function transformerNotationFocus(options = {}) {
350
360
  matchAlgorithm: options.matchAlgorithm
351
361
  }, "@shikijs/transformers:notation-focus");
352
362
  }
353
-
354
363
  //#endregion
355
364
  //#region src/transformers/notation-highlight.ts
356
365
  /**
@@ -368,7 +377,6 @@ function transformerNotationHighlight(options = {}) {
368
377
  matchAlgorithm: options.matchAlgorithm
369
378
  }, "@shikijs/transformers:notation-highlight");
370
379
  }
371
-
372
380
  //#endregion
373
381
  //#region src/shared/highlight-word.ts
374
382
  function highlightWordInLine(line, ignoredElement, word, className) {
@@ -433,20 +441,20 @@ function inheritElement(original, overrides) {
433
441
  ...overrides
434
442
  };
435
443
  }
436
-
437
444
  //#endregion
438
445
  //#region src/transformers/notation-highlight-word.ts
446
+ const RE_CODE_WORD = /\s*\[!code word:((?:\\.|[^:\]])+)(:\d+)?\]/;
447
+ const RE_UNESCAPE = /\\(.)/g;
439
448
  function transformerNotationWordHighlight(options = {}) {
440
449
  const { classActiveWord = "highlighted-word", classActivePre = void 0 } = options;
441
- return createCommentNotationTransformer("@shikijs/transformers:notation-highlight-word", /\s*\[!code word:((?:\\.|[^:\]])+)(:\d+)?\]/, function([_, word, range], _line, comment, lines, index) {
450
+ return createCommentNotationTransformer("@shikijs/transformers:notation-highlight-word", RE_CODE_WORD, function([_, word, range], _line, comment, lines, index) {
442
451
  const lineNum = range ? Number.parseInt(range.slice(1), 10) : lines.length;
443
- word = word.replace(/\\(.)/g, "$1");
452
+ word = word.replace(RE_UNESCAPE, "$1");
444
453
  for (let i = index; i < Math.min(index + lineNum, lines.length); i++) highlightWordInLine.call(this, lines[i], comment, word, classActiveWord);
445
454
  if (classActivePre) this.addClassToHast(this.pre, classActivePre);
446
455
  return true;
447
456
  }, options.matchAlgorithm);
448
457
  }
449
-
450
458
  //#endregion
451
459
  //#region src/transformers/remove-comments.ts
452
460
  /**
@@ -475,7 +483,6 @@ function transformerRemoveComments(options = {}) {
475
483
  }
476
484
  };
477
485
  }
478
-
479
486
  //#endregion
480
487
  //#region src/transformers/remove-line-breaks.ts
481
488
  /**
@@ -490,7 +497,6 @@ function transformerRemoveLineBreak() {
490
497
  }
491
498
  };
492
499
  }
493
-
494
500
  //#endregion
495
501
  //#region src/transformers/remove-notation-escape.ts
496
502
  /**
@@ -511,9 +517,10 @@ function transformerRemoveNotationEscape() {
511
517
  }
512
518
  };
513
519
  }
514
-
515
520
  //#endregion
516
521
  //#region src/transformers/render-indent-guides.ts
522
+ const RE_INDENT_META = /\{indent:(\d+|false)\}/;
523
+ const RE_NON_BLANK = /[^ \t]/;
517
524
  /**
518
525
  * Render indentations as separate tokens.
519
526
  * Apply with CSS, it can be used to render indent guides visually.
@@ -522,7 +529,7 @@ function transformerRenderIndentGuides(options = {}) {
522
529
  return {
523
530
  name: "@shikijs/transformers:render-indent-guides",
524
531
  code(hast) {
525
- const indent = Number(this.options.meta?.indent ?? this.options.meta?.__raw?.match(/\{indent:(\d+|false)\}/)?.[1] ?? options.indent ?? 2);
532
+ const indent = Number(this.options.meta?.indent ?? this.options.meta?.__raw?.match(RE_INDENT_META)?.[1] ?? options.indent ?? 2);
526
533
  if (Number.isNaN(indent) || indent <= 0) return hast;
527
534
  const indentRegex = new RegExp(` {${indent}}| {0,${indent - 1}}\t| {1,}$`, "g");
528
535
  const emptyLines = [];
@@ -535,7 +542,7 @@ function transformerRenderIndentGuides(options = {}) {
535
542
  continue;
536
543
  }
537
544
  const text = first.children[0];
538
- const blanks = text.value.split(/[^ \t]/, 1)[0];
545
+ const blanks = text.value.split(RE_NON_BLANK, 1)[0];
539
546
  const ranges = [];
540
547
  for (const match of blanks.matchAll(indentRegex)) {
541
548
  const start = match.index;
@@ -570,7 +577,6 @@ function transformerRenderIndentGuides(options = {}) {
570
577
  }
571
578
  };
572
579
  }
573
-
574
580
  //#endregion
575
581
  //#region src/shared/utils.ts
576
582
  function isTab(part) {
@@ -613,9 +619,9 @@ function splitSpaces(parts, type, renderContinuousSpaces = true) {
613
619
  ...parts.slice(parts.length - rightCount)
614
620
  ];
615
621
  }
616
-
617
622
  //#endregion
618
623
  //#region src/transformers/render-whitespace.ts
624
+ const RE_SPACE_OR_TAB = /([ \t])/;
619
625
  /**
620
626
  * Render whitespaces as separate tokens.
621
627
  * Apply with CSS, it can be used to render tabs and spaces visually.
@@ -643,7 +649,7 @@ function transformerRenderWhitespace(options = {}) {
643
649
  if (position === "leading" && index !== 0) return token;
644
650
  const node = token.children[0];
645
651
  if (node.type !== "text" || !node.value) return token;
646
- const parts = splitSpaces(node.value.split(/([ \t])/).filter((i) => i.length), position === "boundary" && index === last && last !== 0 ? "trailing" : position, position !== "trailing" && position !== "leading");
652
+ const parts = splitSpaces(node.value.split(RE_SPACE_OR_TAB).filter((i) => i.length), position === "boundary" && index === last && last !== 0 ? "trailing" : position, position !== "trailing" && position !== "leading");
647
653
  if (parts.length <= 1) return token;
648
654
  return parts.map((part) => {
649
655
  const clone = {
@@ -665,7 +671,6 @@ function transformerRenderWhitespace(options = {}) {
665
671
  }
666
672
  };
667
673
  }
668
-
669
674
  //#endregion
670
675
  //#region src/transformers/style-to-class.ts
671
676
  /**
@@ -734,6 +739,5 @@ function cyrb53(str, seed = 0) {
734
739
  h2 ^= Math.imul(h1 ^ h1 >>> 13, 3266489909);
735
740
  return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36).slice(0, 6);
736
741
  }
737
-
738
742
  //#endregion
739
- export { createCommentNotationTransformer, findAllSubstringIndexes, parseMetaHighlightString, parseMetaHighlightWords, transformerCompactLineOptions, transformerMetaHighlight, transformerMetaWordHighlight, transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationMap, transformerNotationWordHighlight, transformerRemoveComments, transformerRemoveLineBreak, transformerRemoveNotationEscape, transformerRenderIndentGuides, transformerRenderWhitespace, transformerStyleToClass };
743
+ export { createCommentNotationTransformer, findAllSubstringIndexes, parseMetaHighlightString, parseMetaHighlightWords, transformerCompactLineOptions, transformerMetaHighlight, transformerMetaWordHighlight, transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationMap, transformerNotationWordHighlight, transformerRemoveComments, transformerRemoveLineBreak, transformerRemoveNotationEscape, transformerRenderIndentGuides, transformerRenderWhitespace, transformerStyleToClass };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/transformers",
3
3
  "type": "module",
4
- "version": "4.0.2",
4
+ "version": "4.2.0",
5
5
  "description": "Collective of common transformers transformers for Shiki",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -30,8 +30,8 @@
30
30
  "node": ">=20"
31
31
  },
32
32
  "dependencies": {
33
- "@shikijs/core": "4.0.2",
34
- "@shikijs/types": "4.0.2"
33
+ "@shikijs/core": "4.2.0",
34
+ "@shikijs/types": "4.2.0"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "tsdown",