@shikijs/engine-javascript 1.17.4 → 1.17.6

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
@@ -3,12 +3,20 @@ import { PatternScanner, RegexEngineString, RegexEngine } from '@shikijs/types';
3
3
  interface JavaScriptRegexEngineOptions {
4
4
  /**
5
5
  * Whether to allow invalid regex patterns.
6
+ *
7
+ * @default false
6
8
  */
7
9
  forgiving?: boolean;
10
+ /**
11
+ * Use JavaScript to simulate some unsupported regex features.
12
+ *
13
+ * @default true
14
+ */
15
+ simulation?: boolean;
8
16
  /**
9
17
  * Cache for regex patterns.
10
18
  */
11
- cache?: Map<string, RegExp | Error>;
19
+ cache?: Map<string, RegExp | Error> | null;
12
20
  /**
13
21
  * Custom pattern to RegExp constructor.
14
22
  *
@@ -22,11 +30,10 @@ interface JavaScriptRegexEngineOptions {
22
30
  declare function defaultJavaScriptRegexConstructor(pattern: string): RegExp;
23
31
  declare class JavaScriptScanner implements PatternScanner {
24
32
  patterns: string[];
25
- cache: Map<string, RegExp | Error>;
26
- forgiving: boolean;
27
- regexConstructor: (pattern: string) => RegExp;
33
+ options: JavaScriptRegexEngineOptions;
28
34
  regexps: (RegExp | null)[];
29
- constructor(patterns: string[], cache: Map<string, RegExp | Error>, forgiving: boolean, regexConstructor?: (pattern: string) => RegExp);
35
+ contiguousAnchorSimulation: boolean[];
36
+ constructor(patterns: string[], options?: JavaScriptRegexEngineOptions);
30
37
  findNextMatchSync(string: string | RegexEngineString, startPosition: number): {
31
38
  index: number;
32
39
  captureIndices: {
package/dist/index.d.ts CHANGED
@@ -3,12 +3,20 @@ import { PatternScanner, RegexEngineString, RegexEngine } from '@shikijs/types';
3
3
  interface JavaScriptRegexEngineOptions {
4
4
  /**
5
5
  * Whether to allow invalid regex patterns.
6
+ *
7
+ * @default false
6
8
  */
7
9
  forgiving?: boolean;
10
+ /**
11
+ * Use JavaScript to simulate some unsupported regex features.
12
+ *
13
+ * @default true
14
+ */
15
+ simulation?: boolean;
8
16
  /**
9
17
  * Cache for regex patterns.
10
18
  */
11
- cache?: Map<string, RegExp | Error>;
19
+ cache?: Map<string, RegExp | Error> | null;
12
20
  /**
13
21
  * Custom pattern to RegExp constructor.
14
22
  *
@@ -22,11 +30,10 @@ interface JavaScriptRegexEngineOptions {
22
30
  declare function defaultJavaScriptRegexConstructor(pattern: string): RegExp;
23
31
  declare class JavaScriptScanner implements PatternScanner {
24
32
  patterns: string[];
25
- cache: Map<string, RegExp | Error>;
26
- forgiving: boolean;
27
- regexConstructor: (pattern: string) => RegExp;
33
+ options: JavaScriptRegexEngineOptions;
28
34
  regexps: (RegExp | null)[];
29
- constructor(patterns: string[], cache: Map<string, RegExp | Error>, forgiving: boolean, regexConstructor?: (pattern: string) => RegExp);
35
+ contiguousAnchorSimulation: boolean[];
36
+ constructor(patterns: string[], options?: JavaScriptRegexEngineOptions);
30
37
  findNextMatchSync(string: string | RegexEngineString, startPosition: number): {
31
38
  index: number;
32
39
  captureIndices: {
package/dist/index.mjs CHANGED
@@ -1,5 +1,16 @@
1
1
  import { onigurumaToRegexp } from 'oniguruma-to-js';
2
2
 
3
+ const replacements = [
4
+ [
5
+ "(?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])",
6
+ "(?<square>[^\\[\\]\\\\]|\\\\.|\\[(?:[^\\[\\]\\\\]|\\\\.|\\[(?:[^\\[\\]\\\\]|\\\\.|\\[(?:[^\\[\\]\\\\])*+\\])*+\\])*+\\])"
7
+ ],
8
+ [
9
+ "(?<url>(?>[^\\s()]+)|\\(\\g<url>*\\))",
10
+ "(?<url>(?>[^\\s()]+)|\\((?:(?>[^\\s()]+)|\\((?:(?>[^\\s()]+)|\\((?>[^\\s()]+)*\\))*\\))*\\))"
11
+ ]
12
+ ];
13
+
3
14
  var __defProp = Object.defineProperty;
4
15
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
16
  var __publicField = (obj, key, value) => {
@@ -17,13 +28,23 @@ function defaultJavaScriptRegexConstructor(pattern) {
17
28
  );
18
29
  }
19
30
  class JavaScriptScanner {
20
- constructor(patterns, cache, forgiving, regexConstructor = defaultJavaScriptRegexConstructor) {
31
+ constructor(patterns, options = {}) {
21
32
  this.patterns = patterns;
22
- this.cache = cache;
23
- this.forgiving = forgiving;
24
- this.regexConstructor = regexConstructor;
33
+ this.options = options;
25
34
  __publicField(this, "regexps");
26
- this.regexps = patterns.map((p) => {
35
+ __publicField(this, "contiguousAnchorSimulation");
36
+ const {
37
+ forgiving = false,
38
+ cache,
39
+ simulation = true,
40
+ regexConstructor = defaultJavaScriptRegexConstructor
41
+ } = options;
42
+ this.contiguousAnchorSimulation = Array.from({ length: patterns.length }, () => false);
43
+ this.regexps = patterns.map((p, idx) => {
44
+ if (simulation)
45
+ p = p.replaceAll("(^|\\\uFFFF)", "(^|\\G)");
46
+ if (simulation && (p.startsWith("(^|\\G)") || p.startsWith("(\\G|^)")))
47
+ this.contiguousAnchorSimulation[idx] = true;
27
48
  const cached = cache?.get(p);
28
49
  if (cached) {
29
50
  if (cached instanceof RegExp) {
@@ -34,7 +55,13 @@ class JavaScriptScanner {
34
55
  throw cached;
35
56
  }
36
57
  try {
37
- const regex = regexConstructor(p);
58
+ let pattern = p;
59
+ if (simulation) {
60
+ for (const [from, to] of replacements) {
61
+ pattern = pattern.replaceAll(from, to);
62
+ }
63
+ }
64
+ const regex = regexConstructor(pattern);
38
65
  cache?.set(p, regex);
39
66
  return regex;
40
67
  } catch (e) {
@@ -48,7 +75,7 @@ class JavaScriptScanner {
48
75
  findNextMatchSync(string, startPosition) {
49
76
  const str = typeof string === "string" ? string : string.content;
50
77
  const pending = [];
51
- function toResult(index, match) {
78
+ function toResult(index, match, offset = 0) {
52
79
  return {
53
80
  index,
54
81
  captureIndices: match.indices.map((indice) => {
@@ -60,9 +87,9 @@ class JavaScriptScanner {
60
87
  };
61
88
  }
62
89
  return {
63
- start: indice[0],
90
+ start: indice[0] + offset,
64
91
  length: indice[1] - indice[0],
65
- end: indice[1]
92
+ end: indice[1] + offset
66
93
  };
67
94
  })
68
95
  };
@@ -72,25 +99,31 @@ class JavaScriptScanner {
72
99
  if (!regexp)
73
100
  continue;
74
101
  try {
102
+ let offset = 0;
75
103
  regexp.lastIndex = startPosition;
76
- const match = regexp.exec(str);
104
+ let match = regexp.exec(str);
105
+ if (!match && this.contiguousAnchorSimulation[i]) {
106
+ offset = startPosition;
107
+ regexp.lastIndex = 0;
108
+ match = regexp.exec(str.slice(startPosition));
109
+ }
77
110
  if (!match)
78
111
  continue;
79
112
  if (match.index === startPosition) {
80
- return toResult(i, match);
113
+ return toResult(i, match, offset);
81
114
  }
82
- pending.push([i, match]);
115
+ pending.push([i, match, offset]);
83
116
  } catch (e) {
84
- if (this.forgiving)
117
+ if (this.options.forgiving)
85
118
  continue;
86
119
  throw e;
87
120
  }
88
121
  }
89
122
  if (pending.length) {
90
123
  const minIndex = Math.min(...pending.map((m) => m[1].index));
91
- for (const [i, match] of pending) {
124
+ for (const [i, match, offset] of pending) {
92
125
  if (match.index === minIndex) {
93
- return toResult(i, match);
126
+ return toResult(i, match, offset);
94
127
  }
95
128
  }
96
129
  }
@@ -98,13 +131,13 @@ class JavaScriptScanner {
98
131
  }
99
132
  }
100
133
  function createJavaScriptRegexEngine(options = {}) {
101
- const {
102
- forgiving = false,
103
- cache = /* @__PURE__ */ new Map()
104
- } = options;
134
+ const _options = {
135
+ cache: /* @__PURE__ */ new Map(),
136
+ ...options
137
+ };
105
138
  return {
106
139
  createScanner(patterns) {
107
- return new JavaScriptScanner(patterns, cache, forgiving, options.regexConstructor);
140
+ return new JavaScriptScanner(patterns, _options);
108
141
  },
109
142
  createString(s) {
110
143
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/engine-javascript",
3
3
  "type": "module",
4
- "version": "1.17.4",
4
+ "version": "1.17.6",
5
5
  "description": "Engine for Shiki using JavaScript's native RegExp",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -30,8 +30,8 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "oniguruma-to-js": "0.4.0",
34
- "@shikijs/types": "1.17.4"
33
+ "oniguruma-to-js": "0.4.3",
34
+ "@shikijs/types": "1.17.6"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "unbuild",