@shikijs/core 1.16.1 → 1.16.2

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.
@@ -49,6 +49,12 @@ interface JavaScriptRegexEngineOptions {
49
49
  * Cache for regex patterns.
50
50
  */
51
51
  cache?: Map<string, RegExp | Error>;
52
+ /**
53
+ * Custom pattern to RegExp constructor.
54
+ *
55
+ * By default `oniguruma-to-js` is used.
56
+ */
57
+ regexConstructor?: (pattern: string) => RegExp;
52
58
  }
53
59
 
54
60
  export type { Awaitable as A, JavaScriptRegexEngineOptions as J, LoadWasmOptions as L, MaybeArray as M, OnigurumaLoadOptions as O, PatternScanner as P, RequireKeys as R, StringLiteralUnion as S, WebAssemblyInstantiator as W, RegexEngine as a, MaybeGetter as b, MaybeModule as c, RegexEngineString as d, WebAssemblyInstance as e, LoadWasmOptionsPlain as f };
package/dist/index.d.mts CHANGED
@@ -131,6 +131,10 @@ declare function loadWasm(options: LoadWasmOptions): Promise<void>;
131
131
 
132
132
  declare function createWasmOnigEngine(options?: LoadWasmOptions | null): Promise<RegexEngine>;
133
133
 
134
+ /**
135
+ * The default RegExp constructor for JavaScript regex engine.
136
+ */
137
+ declare function defaultJavaScriptRegexConstructor(pattern: string): RegExp;
134
138
  /**
135
139
  * Use the modern JavaScript RegExp engine to implement the OnigScanner.
136
140
  *
@@ -470,4 +474,4 @@ declare class ShikiError extends Error {
470
474
  constructor(message: string);
471
475
  }
472
476
 
473
- export { BundledHighlighterOptions, CodeToHastOptions, CodeToHastRenderOptions, CodeToTokensBaseOptions, CodeToTokensOptions, CodeToTokensWithThemesOptions, type CreateHighlighterFactory, CreatedBundledHighlighterOptions, GrammarState, HighlighterCore, HighlighterCoreOptions, HighlighterGeneric, JavaScriptRegexEngineOptions, LanguageInput, LoadWasmOptions, MaybeArray, MaybeGetter, PlainTextLanguage, Position, RegexEngine, RequireKeys, ShikiError, ShikiInternal, ShikiTransformer, ShikiTransformerContextCommon, ShikiTransformerContextSource, type ShorthandsBundle, SpecialLanguage, SpecialTheme, ThemeInput, ThemeRegistrationAny, ThemeRegistrationResolved, ThemedToken, ThemedTokenWithVariants, TokenStyles, TokenizeWithThemeOptions, TokensResult, addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createHighlighterCore, createHighlighterCoreSync, createJavaScriptRegexEngine, createPositionConverter, createShikiInternal, createShikiInternalSync, createSingletonShorthands, createWasmOnigEngine, createdBundledHighlighter, getHighlighterCore, getShikiInternal, getSingletonHighlighterCore, getTokenStyleObject, toHtml as hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, loadWasm, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, setDefaultWasmLoader, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations };
477
+ export { BundledHighlighterOptions, CodeToHastOptions, CodeToHastRenderOptions, CodeToTokensBaseOptions, CodeToTokensOptions, CodeToTokensWithThemesOptions, type CreateHighlighterFactory, CreatedBundledHighlighterOptions, GrammarState, HighlighterCore, HighlighterCoreOptions, HighlighterGeneric, JavaScriptRegexEngineOptions, LanguageInput, LoadWasmOptions, MaybeArray, MaybeGetter, PlainTextLanguage, Position, RegexEngine, RequireKeys, ShikiError, ShikiInternal, ShikiTransformer, ShikiTransformerContextCommon, ShikiTransformerContextSource, type ShorthandsBundle, SpecialLanguage, SpecialTheme, ThemeInput, ThemeRegistrationAny, ThemeRegistrationResolved, ThemedToken, ThemedTokenWithVariants, TokenStyles, TokenizeWithThemeOptions, TokensResult, addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createHighlighterCore, createHighlighterCoreSync, createJavaScriptRegexEngine, createPositionConverter, createShikiInternal, createShikiInternalSync, createSingletonShorthands, createWasmOnigEngine, createdBundledHighlighter, defaultJavaScriptRegexConstructor, getHighlighterCore, getShikiInternal, getSingletonHighlighterCore, getTokenStyleObject, toHtml as hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, loadWasm, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, setDefaultWasmLoader, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations };
package/dist/index.mjs CHANGED
@@ -106,7 +106,8 @@ function splitToken(token, offsets) {
106
106
  * Split 2D tokens array by given breakpoints.
107
107
  */
108
108
  function splitTokens(tokens, breakpoints) {
109
- const sorted = Array.from(breakpoints instanceof Set ? breakpoints : new Set(breakpoints))
109
+ const sorted = Array
110
+ .from(breakpoints instanceof Set ? breakpoints : new Set(breakpoints))
110
111
  .sort((a, b) => a - b);
111
112
  if (!sorted.length)
112
113
  return tokens;
@@ -752,7 +753,8 @@ function dimColor(color) {
752
753
  if (hexMatch) {
753
754
  if (hexMatch[3]) {
754
755
  // convert from #rrggbbaa to #rrggbb(aa/2)
755
- const alpha = Math.round(Number.parseInt(hexMatch[3], 16) / 2)
756
+ const alpha = Math
757
+ .round(Number.parseInt(hexMatch[3], 16) / 2)
756
758
  .toString(16)
757
759
  .padStart(2, '0');
758
760
  return `#${hexMatch[1]}${hexMatch[2]}${alpha}`;
@@ -763,7 +765,8 @@ function dimColor(color) {
763
765
  }
764
766
  else {
765
767
  // convert from #rgb to #rrggbb80
766
- return `#${Array.from(hexMatch[1])
768
+ return `#${Array
769
+ .from(hexMatch[1])
767
770
  .map(x => `${x}${x}`)
768
771
  .join('')}80`;
769
772
  }
@@ -964,7 +967,8 @@ function explainThemeScope(themeSettingsSelectors, scope, parentScopes) {
964
967
  * Get tokens with multiple themes
965
968
  */
966
969
  function codeToTokensWithThemes(internal, code, options) {
967
- const themes = Object.entries(options.themes)
970
+ const themes = Object
971
+ .entries(options.themes)
968
972
  .filter(i => i[1])
969
973
  .map(i => ({ color: i[0], theme: i[1] }));
970
974
  const tokens = syncThemesTokenization(...themes.map(t => codeToTokensBase(internal, code, {
@@ -1051,7 +1055,8 @@ function codeToTokens(internal, code, options) {
1051
1055
  let rootStyle;
1052
1056
  if ('themes' in options) {
1053
1057
  const { defaultColor = 'light', cssVariablePrefix = '--shiki-', } = options;
1054
- const themes = Object.entries(options.themes)
1058
+ const themes = Object
1059
+ .entries(options.themes)
1055
1060
  .filter(i => i[1])
1056
1061
  .map(i => ({ color: i[0], theme: i[1] }))
1057
1062
  .sort((a, b) => a.color === defaultColor ? -1 : b.color === defaultColor ? 1 : 0);
@@ -5862,6 +5867,8 @@ class RegExpConversionError extends SyntaxError {
5862
5867
  }
5863
5868
  }
5864
5869
 
5870
+ const UNNECESSARY_ESCAPE_CHAR_CLASS = new Set("!?:=+$(){}_><# ");
5871
+ const UNNECESSARY_ESCAPE = new Set("-!:=_>< ");
5865
5872
  const TABLE_POSIX = {
5866
5873
  alnum: "0-9A-Za-z",
5867
5874
  alpha: "A-Za-z",
@@ -5878,13 +5885,23 @@ const TABLE_POSIX = {
5878
5885
  xdigit: "0-9A-Fa-f",
5879
5886
  word: "\\w"
5880
5887
  };
5888
+ const TABLE_SLASH_P = {
5889
+ alnum: "0-9A-Za-z",
5890
+ alpha: "A-Za-z",
5891
+ alphabetic: "A-Za-z",
5892
+ blank: "\\s",
5893
+ greek: "\\p{Script=Greek}",
5894
+ print: "\\p{L}\\p{N}\\p{P}\\p{S}\\p{Zs}",
5895
+ word: "\\w"
5896
+ };
5881
5897
  const KNOWN_FLAGS = /* @__PURE__ */ new Set("gimsuyx");
5882
5898
  function syntaxLowering(input, options = {}) {
5883
5899
  const {
5884
5900
  preserveFlags = false,
5885
5901
  removePossessiveQuantifier = false,
5886
5902
  removeAtomicGroup = false,
5887
- convertHexDigitsShorthand = false
5903
+ convertHexDigitsShorthand = false,
5904
+ convertUnicodeCategory = false
5888
5905
  } = options;
5889
5906
  let output = "";
5890
5907
  const flags = /* @__PURE__ */ new Set();
@@ -5899,7 +5916,7 @@ function syntaxLowering(input, options = {}) {
5899
5916
  freeSpacingLocal.shift();
5900
5917
  }
5901
5918
  const head = stack[0];
5902
- const wsEscape = freeSpacingGlobal || freeSpacingLocal.length;
5919
+ const freeSpacing = freeSpacingGlobal || freeSpacingLocal.length;
5903
5920
  if (char === "\\") {
5904
5921
  if (convertHexDigitsShorthand) {
5905
5922
  if (input[i + 1] === "h") {
@@ -5925,11 +5942,41 @@ function syntaxLowering(input, options = {}) {
5925
5942
  continue;
5926
5943
  }
5927
5944
  }
5945
+ if (convertUnicodeCategory && input[i + 1] === "p" && input[i + 2] === "{") {
5946
+ const end = input.indexOf("}", i + 3);
5947
+ if (end === -1) {
5948
+ throw new RegExpConversionError(
5949
+ "Unmatched \\p{...}",
5950
+ { pattern: input, converted: output, cursor: i }
5951
+ );
5952
+ }
5953
+ const name = input.slice(i + 3, end);
5954
+ const resolved = TABLE_SLASH_P[name.toLowerCase()];
5955
+ if (resolved) {
5956
+ if (head === "[") {
5957
+ output += resolved;
5958
+ } else {
5959
+ output += `[${resolved}]`;
5960
+ }
5961
+ i = end + 1;
5962
+ continue;
5963
+ }
5964
+ }
5965
+ if (head === "[" && UNNECESSARY_ESCAPE_CHAR_CLASS.has(input[i + 1])) {
5966
+ output += input[i + 1];
5967
+ i += 2;
5968
+ continue;
5969
+ }
5970
+ if (head !== "[" && UNNECESSARY_ESCAPE.has(input[i + 1])) {
5971
+ output += input[i + 1];
5972
+ i += 2;
5973
+ continue;
5974
+ }
5928
5975
  output += char + input[i + 1];
5929
5976
  i += 2;
5930
5977
  continue;
5931
5978
  }
5932
- if (char === "#" && wsEscape && input[i - 1].match(/\s/) && head !== "[") {
5979
+ if (char === "#" && freeSpacing && input[i - 1].match(/\s/) && head !== "[") {
5933
5980
  for (let j = i + 1; j <= input.length; j++) {
5934
5981
  if (input[j] === "\n" || j === input.length) {
5935
5982
  i = j;
@@ -6068,7 +6115,7 @@ function syntaxLowering(input, options = {}) {
6068
6115
  continue;
6069
6116
  }
6070
6117
  }
6071
- if (!(wsEscape && head !== "[" && char.match(/\s/))) {
6118
+ if (!(freeSpacing && head !== "[" && char.match(/\s/))) {
6072
6119
  output += char;
6073
6120
  }
6074
6121
  i += 1;
@@ -6108,7 +6155,9 @@ function construct(pattern, options = {}) {
6108
6155
  if (options.ignoreContiguousAnchors) {
6109
6156
  pattern = pattern.replace(/\\G/g, "");
6110
6157
  }
6111
- pattern = pattern.replace(/\\A/g, "^").replace(/\\x\{([^}]*)\}/g, (m, hex) => `\\u${hex.padStart(4, "0")}`).replace(/\(\?(-)?(\w+):/g, (_, neg, flagStr) => {
6158
+ if (pattern.includes("\\p{"))
6159
+ flagSet.add("u");
6160
+ pattern = pattern.replace(/\\A/g, "^").replace(/\\Z/gi, "$").replace(/\\x\{([^}]*)\}/g, (m, hex) => `\\u${hex.padStart(4, "0")}`).replace(/\(\?(-)?(\w+):/g, (_, neg, flagStr) => {
6112
6161
  if (neg) {
6113
6162
  for (const flag of flagStr)
6114
6163
  flagSet.delete(flag);
@@ -6155,6 +6204,7 @@ function onigurumaToRegexp(pattern, options = {}) {
6155
6204
  removePossessiveQuantifier: true,
6156
6205
  removeAtomicGroup: true,
6157
6206
  convertHexDigitsShorthand: true,
6207
+ convertUnicodeCategory: true,
6158
6208
  ...options
6159
6209
  });
6160
6210
  return construct(converted, {
@@ -6165,15 +6215,30 @@ function onigurumaToRegexp(pattern, options = {}) {
6165
6215
  }
6166
6216
 
6167
6217
  const MAX = 4294967295;
6218
+ /**
6219
+ * The default RegExp constructor for JavaScript regex engine.
6220
+ */
6221
+ function defaultJavaScriptRegexConstructor(pattern) {
6222
+ return onigurumaToRegexp(pattern
6223
+ .replace(/\|\\G(\||\))/g, '$1')
6224
+ .replace(/(\(|\|)\\G\|/g, '$1')
6225
+ // YAML specific handling; TODO: move to tm-grammars
6226
+ .replaceAll('[^\\s[-?:,\\[\\]{}#&*!|>\'"%@`]]', '[^\\s\\-?:,\\[\\]{}#&*!|>\'"%@`]'), {
6227
+ flags: 'dgm',
6228
+ ignoreContiguousAnchors: true,
6229
+ });
6230
+ }
6168
6231
  class JavaScriptScanner {
6169
6232
  patterns;
6170
6233
  cache;
6171
6234
  forgiving;
6235
+ regexConstructor;
6172
6236
  regexps;
6173
- constructor(patterns, cache, forgiving) {
6237
+ constructor(patterns, cache, forgiving, regexConstructor = defaultJavaScriptRegexConstructor) {
6174
6238
  this.patterns = patterns;
6175
6239
  this.cache = cache;
6176
6240
  this.forgiving = forgiving;
6241
+ this.regexConstructor = regexConstructor;
6177
6242
  this.regexps = patterns.map((p) => {
6178
6243
  const cached = cache?.get(p);
6179
6244
  if (cached) {
@@ -6185,14 +6250,7 @@ class JavaScriptScanner {
6185
6250
  throw cached;
6186
6251
  }
6187
6252
  try {
6188
- const regex = onigurumaToRegexp(p
6189
- .replace(/\|\\G(\||\))/g, '$1')
6190
- .replace(/(\(|\|)\\G\|/g, '$1')
6191
- // YAML specific handling; TODO: move to tm-grammars
6192
- .replaceAll('[^\\s[-?:,\\[\\]{}#&*!|>\'"%@`]]', '[^\\s\\-?:,\\[\\]{}#&*!|>\'"%@`]'), {
6193
- flags: 'dgm',
6194
- ignoreContiguousAnchors: true,
6195
- });
6253
+ const regex = regexConstructor(p);
6196
6254
  cache?.set(p, regex);
6197
6255
  return regex;
6198
6256
  }
@@ -6276,7 +6334,7 @@ function createJavaScriptRegexEngine(options = {}) {
6276
6334
  const { forgiving = false, cache = new Map(), } = options;
6277
6335
  return {
6278
6336
  createScanner(patterns) {
6279
- return new JavaScriptScanner(patterns, cache, forgiving);
6337
+ return new JavaScriptScanner(patterns, cache, forgiving, options.regexConstructor);
6280
6338
  },
6281
6339
  createString(s) {
6282
6340
  return {
@@ -6286,4 +6344,4 @@ function createJavaScriptRegexEngine(options = {}) {
6286
6344
  };
6287
6345
  }
6288
6346
 
6289
- export { FontStyle, ShikiError, addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createHighlighterCore, createHighlighterCoreSync, createJavaScriptRegexEngine, createPositionConverter, createShikiInternal, createShikiInternalSync, createSingletonShorthands, createWasmOnigEngine, createdBundledHighlighter, getHighlighterCore, getShikiInternal, getSingletonHighlighterCore, getTokenStyleObject, toHtml as hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, loadWasm, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, setDefaultWasmLoader, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations };
6347
+ export { FontStyle, ShikiError, addClassToHast, applyColorReplacements, codeToHast, codeToHtml, codeToTokens, codeToTokensBase, codeToTokensWithThemes, createHighlighterCore, createHighlighterCoreSync, createJavaScriptRegexEngine, createPositionConverter, createShikiInternal, createShikiInternalSync, createSingletonShorthands, createWasmOnigEngine, createdBundledHighlighter, defaultJavaScriptRegexConstructor, getHighlighterCore, getShikiInternal, getSingletonHighlighterCore, getTokenStyleObject, toHtml as hastToHtml, isNoneTheme, isPlainLang, isSpecialLang, isSpecialTheme, loadWasm, makeSingletonHighlighter, makeSingletonHighlighterCore, normalizeGetter, normalizeTheme, resolveColorReplacements, setDefaultWasmLoader, splitLines, splitToken, splitTokens, stringifyTokenStyle, toArray, tokenizeAnsiWithTheme, tokenizeWithTheme, tokensToHast, transformerDecorations };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/core",
3
3
  "type": "module",
4
- "version": "1.16.1",
4
+ "version": "1.16.2",
5
5
  "description": "Core of Shiki",
6
6
  "author": "Pine Wu <octref@gmail.com>; Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "devDependencies": {
67
67
  "hast-util-to-html": "^9.0.2",
68
- "oniguruma-to-js": "^0.3.0",
68
+ "oniguruma-to-js": "^0.3.1",
69
69
  "vscode-oniguruma": "^1.7.0"
70
70
  },
71
71
  "scripts": {