Skip to content

Commit 33b8b49

Browse files
slevithanantfu
andauthoredNov 15, 2024··
feat: Use Oniguruma-To-ES in the JS engine (#828) (#832)
Co-authored-by: Anthony Fu <github@antfu.me>
1 parent 94cc6d8 commit 33b8b49

19 files changed

+252
-462
lines changed
 

Diff for: ‎.github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ jobs:
6565
node: [lts/*]
6666
os: [ubuntu-latest, windows-latest, macos-latest]
6767
include:
68+
- node: 20.x
69+
os: ubuntu-latest
6870
- node: 18.x
6971
os: ubuntu-latest
7072
fail-fast: false

Diff for: ‎docs/guide/regex-engines.md

+21-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ outline: deep
44

55
# RegExp Engines
66

7-
TextMate grammars is based on regular expressions to match tokens. Usually, we use [Oniguruma](https://github.com/kkos/oniguruma) (a regular expression engine written in C) to parse the grammar. To make it work in JavaScript, we compile Oniguruma to WebAssembly to run in the browser or Node.js.
7+
TextMate grammars are based on regular expressions to match tokens. Usually, we use [Oniguruma](https://github.com/kkos/oniguruma) (a regular expression engine written in C) to parse the grammar. To make it work in JavaScript, we compile Oniguruma to WebAssembly to run in the browser or Node.js.
88

99
Since v1.15, we expose the ability to for users to switch the RegExp engine and provide custom implementations.
1010

@@ -20,7 +20,7 @@ const shiki = await createShiki({
2020
})
2121
```
2222

23-
Shiki come with two built-in engines:
23+
Shiki comes with two built-in engines:
2424

2525
## Oniguruma Engine
2626

@@ -43,7 +43,7 @@ const shiki = await createShiki({
4343
This feature is experimental and may change without following semver.
4444
:::
4545

46-
This experimental engine uses JavaScript's native RegExp. As TextMate grammars' regular expressions are in Oniguruma flavor that might contains syntaxes that are not supported by JavaScript's RegExp, we use [`oniguruma-to-js`](https://github.com/antfu/oniguruma-to-js) to lowering the syntaxes and try to make them compatible with JavaScript's RegExp.
46+
This engine uses JavaScript's native RegExp. As regular expressions used by TextMate grammars are written for Oniguruma, they might contain syntax that is not supported by JavaScript's RegExp, or expect different behavior for the same syntax. So we use [Oniguruma-To-ES](https://github.com/slevithan/oniguruma-to-es) to transpile Oniguruma patterns to native JavaScript RegExp.
4747

4848
```ts {2,4,9}
4949
import { createHighlighter } from 'shiki'
@@ -60,17 +60,31 @@ const shiki = await createHighlighter({
6060
const html = shiki.codeToHtml('const a = 1', { lang: 'javascript', theme: 'nord' })
6161
```
6262

63-
Please check the [compatibility table](/references/engine-js-compat) to check the support status of the languages you are using.
63+
Please check the [compatibility table](/references/engine-js-compat) for the support status of the languages you are using.
6464

65-
If mismatches are acceptable and you want it to get results whatever it can, you can enable the `forgiving` option to suppress any errors happened during the conversion:
65+
Unlike the Oniguruma engine, the JavaScript engine is strict by default. It will throw an error if it encounters a pattern that it cannot convert. If mismatches are acceptable and you want best-effort results whenever possible, you can enable the `forgiving` option to suppress any errors that happened during the conversion:
6666

6767
```ts
6868
const jsEngine = createJavaScriptRegexEngine({ forgiving: true })
6969
// ...use the engine
7070
```
7171

7272
::: info
73-
If you runs Shiki on Node.js (or at build time), we still recommend using the Oniguruma engine for the best result, as most of the time bundle size or WebAssembly support is not a concern.
73+
If you run Shiki on Node.js (or at build time) and bundle size or WebAssembly support is not a concern, we still recommend using the Oniguruma engine for the best result.
7474

75-
The JavaScript engine is more suitable for running in the browser in some cases that you want to control the bundle size.
75+
The JavaScript engine is best when running in the browser and in cases when you want to control the bundle size.
7676
:::
77+
78+
### JavaScript Runtime Target
79+
80+
For the most accurate result, [Oniguruma-To-ES](https://github.com/slevithan/oniguruma-to-es) requires the [RegExp `v` flag support](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicodeSets), which is available in Node.js v20+ and ES2024 ([Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicodeSets#browser_compatibility)).
81+
82+
For older environments, it can simulate the behavior but `u` flag but might yield less accurate results.
83+
84+
By default, it automatically detects the runtime target and uses the appropriate behavior. You can override this behavior by setting the `target` option:
85+
86+
```ts
87+
const jsEngine = createJavaScriptRegexEngine({
88+
target: 'ES2018', // or 'ES2024', default is 'auto'
89+
})
90+
```

Diff for: ‎docs/references/engine-js-compat.md

+40-40
Large diffs are not rendered by default.

Diff for: ‎packages/core/rollup.config.mjs

+2-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@ const external = [
3636
'hast',
3737
'@shikijs/vscode-textmate',
3838

39-
// Externalize them to make it easier to patch and experiments
39+
// Externalize to make it easier to patch and experiment
4040
// Versions are pinned to avoid regressions
41-
// Later we might consider to bundle them.
42-
'oniguruma-to-js',
43-
'regex',
41+
'oniguruma-to-es',
4442
]
4543

4644
export default defineConfig([

Diff for: ‎packages/engine-javascript/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# @shikijs/engine-javascript
22

3-
Engine for Shiki using JavaScript's native RegExp (experimental).
3+
Engine for Shiki using JavaScript's native RegExp (experimental). Uses [Oniguruma-To-ES](https://github.com/slevithan/oniguruma-to-es) to transpile regex syntax and behavior.
44

55
[Documentation](https://shiki.style/guide/regex-engines)
66

Diff for: ‎packages/engine-javascript/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@
3737
"dependencies": {
3838
"@shikijs/types": "workspace:*",
3939
"@shikijs/vscode-textmate": "catalog:",
40-
"oniguruma-to-js": "catalog:"
40+
"oniguruma-to-es": "catalog:"
4141
}
4242
}

Diff for: ‎packages/engine-javascript/scripts/generate.ts

-48
This file was deleted.

Diff for: ‎packages/engine-javascript/scripts/utils.ts

-20
This file was deleted.

Diff for: ‎packages/engine-javascript/src/index.ts

+63-36
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import type {
44
RegexEngineString,
55
} from '@shikijs/types'
66
import type { IOnigMatch } from '@shikijs/vscode-textmate'
7-
import { onigurumaToRegexp } from 'oniguruma-to-js'
8-
import { replacements } from './replacements'
7+
import type { Options as OnigurumaToEsOptions } from 'oniguruma-to-es'
8+
import { toRegExp } from 'oniguruma-to-es'
99

1010
export interface JavaScriptRegexEngineOptions {
1111
/**
@@ -16,12 +16,27 @@ export interface JavaScriptRegexEngineOptions {
1616
forgiving?: boolean
1717

1818
/**
19-
* Use JavaScript to simulate some unsupported regex features.
19+
* Cleanup some grammar patterns before use.
2020
*
2121
* @default true
2222
*/
2323
simulation?: boolean
2424

25+
/**
26+
* The target ECMAScript version.
27+
*
28+
* For the best accuracy, Oniguruma-to-ES needs the `v` flag support in RegExp which is landed in ES2024.
29+
* Which requires Node.js 20+ or Chrome 112+.
30+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicodeSets
31+
*
32+
* For the maximum compatibility, you can set it to `ES2018`. Which will use the `u` flag to simulate and will be less accurate.
33+
*
34+
* Set to `auto` to detect the target version automatically.
35+
*
36+
* @default 'auto'
37+
*/
38+
target?: 'ES2024' | 'ES2025' | 'ES2018' | 'auto'
39+
2540
/**
2641
* Cache for regex patterns.
2742
*/
@@ -30,29 +45,53 @@ export interface JavaScriptRegexEngineOptions {
3045
/**
3146
* Custom pattern to RegExp constructor.
3247
*
33-
* By default `oniguruma-to-js` is used.
48+
* By default `oniguruma-to-es` is used.
3449
*/
3550
regexConstructor?: (pattern: string) => RegExp
3651
}
3752

53+
type NonNullable<T> = T extends null | undefined ? never : T
54+
3855
const MAX = 4294967295
3956

57+
let supportedRegExpTarget: OnigurumaToEsOptions['target'] | undefined
58+
59+
function detectRegExpTarget(): NonNullable<OnigurumaToEsOptions['target']> {
60+
if (supportedRegExpTarget != null)
61+
return supportedRegExpTarget
62+
63+
supportedRegExpTarget = 'ES2018'
64+
65+
try {
66+
// eslint-disable-next-line prefer-regex-literals, no-new
67+
new RegExp('a', 'v')
68+
supportedRegExpTarget = 'ES2024'
69+
}
70+
catch {
71+
supportedRegExpTarget = 'ES2018'
72+
}
73+
74+
return supportedRegExpTarget
75+
}
76+
4077
/**
4178
* The default RegExp constructor for JavaScript regex engine.
4279
*/
43-
export function defaultJavaScriptRegexConstructor(pattern: string): RegExp {
44-
return onigurumaToRegexp(
80+
export function defaultJavaScriptRegexConstructor(pattern: string, options?: OnigurumaToEsOptions): RegExp {
81+
return toRegExp(
4582
pattern,
4683
{
47-
flags: 'dgm',
48-
ignoreContiguousAnchors: true,
84+
accuracy: 'loose',
85+
global: true,
86+
hasIndices: true,
87+
tmGrammar: true,
88+
...options,
4989
},
5090
)
5191
}
5292

5393
export class JavaScriptScanner implements PatternScanner {
5494
regexps: (RegExp | null)[]
55-
contiguousAnchorSimulation: boolean[]
5695

5796
constructor(
5897
public patterns: string[],
@@ -61,12 +100,16 @@ export class JavaScriptScanner implements PatternScanner {
61100
const {
62101
forgiving = false,
63102
cache,
103+
target = 'auto',
64104
simulation = true,
65-
regexConstructor = defaultJavaScriptRegexConstructor,
105+
regexConstructor = (pattern: string) => defaultJavaScriptRegexConstructor(pattern, {
106+
target: target === 'auto'
107+
? detectRegExpTarget()
108+
: target,
109+
}),
66110
} = options
67111

68-
this.contiguousAnchorSimulation = Array.from({ length: patterns.length }, () => false)
69-
this.regexps = patterns.map((p, idx) => {
112+
this.regexps = patterns.map((p) => {
70113
/**
71114
* vscode-textmate replace anchors to \uFFFF, where we still not sure how to handle it correctly
72115
*
@@ -77,10 +120,6 @@ export class JavaScriptScanner implements PatternScanner {
77120
if (simulation)
78121
p = p.replaceAll('(^|\\\uFFFF)', '(^|\\G)')
79122

80-
// Detect contiguous anchors for simulation
81-
if (simulation && (p.startsWith('(^|\\G)') || p.startsWith('(\\G|^)')))
82-
this.contiguousAnchorSimulation[idx] = true
83-
84123
// Cache
85124
const cached = cache?.get(p)
86125
if (cached) {
@@ -92,13 +131,7 @@ export class JavaScriptScanner implements PatternScanner {
92131
throw cached
93132
}
94133
try {
95-
let pattern = p
96-
if (simulation) {
97-
for (const [from, to] of replacements) {
98-
pattern = pattern.replaceAll(from, to)
99-
}
100-
}
101-
const regex = regexConstructor(pattern)
134+
const regex = regexConstructor(p)
102135
cache?.set(p, regex)
103136
return regex
104137
}
@@ -143,25 +176,18 @@ export class JavaScriptScanner implements PatternScanner {
143176
if (!regexp)
144177
continue
145178
try {
146-
let offset = 0
147179
regexp.lastIndex = startPosition
148-
let match = regexp.exec(str)
180+
const match = regexp.exec(str)
149181

150-
// If a regex starts with `(^|\\G)` or `(\\G|^)`, we simulate the behavior by cutting the string
151-
if (!match && this.contiguousAnchorSimulation[i]) {
152-
offset = startPosition
153-
regexp.lastIndex = 0
154-
match = regexp.exec(str.slice(startPosition))
155-
}
156182
if (!match)
157183
continue
158184

159185
// If the match is at the start position, return it immediately
160186
if (match.index === startPosition) {
161-
return toResult(i, match, offset)
187+
return toResult(i, match, 0)
162188
}
163189
// Otherwise, store it for later
164-
pending.push([i, match, offset])
190+
pending.push([i, match, 0])
165191
}
166192
catch (e) {
167193
if (this.options.forgiving)
@@ -187,9 +213,10 @@ export class JavaScriptScanner implements PatternScanner {
187213
/**
188214
* Use the modern JavaScript RegExp engine to implement the OnigScanner.
189215
*
190-
* As Oniguruma regex is more powerful than JavaScript regex, some patterns may not be supported.
191-
* Errors will be thrown when parsing TextMate grammars with unsupported patterns.
192-
* Set `forgiving` to `true` to ignore these errors and skip the unsupported patterns.
216+
* As Oniguruma supports some features that can't be emulated using native JavaScript regexes, some
217+
* patterns are not supported. Errors will be thrown when parsing TextMate grammars with
218+
* unsupported patterns, and when the grammar includes patterns that use invalid Oniguruma syntax.
219+
* Set `forgiving` to `true` to ignore these errors and skip any unsupported or invalid patterns.
193220
*
194221
* @experimental
195222
*/

Diff for: ‎packages/engine-javascript/src/replacements.ts

-12
This file was deleted.

Diff for: ‎packages/engine-javascript/test/compare.test.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import { OnigScanner, OnigString } from '../../engine-oniguruma/src/oniguruma'
77
import { createHighlighterCore } from '../../shiki/src/core'
88
import { createJavaScriptRegexEngine } from '../src'
99

10-
await loadWasm(import('@shikijs/core/wasm-inlined'))
11-
1210
function createWasmOnigLibWrapper(): RegexEngine & { instances: Instance[] } {
1311
const instances: Instance[] = []
1412

@@ -144,7 +142,11 @@ const cases: Cases[] = [
144142
},
145143
]
146144

147-
describe('cases', async () => {
145+
describe.skipIf(
146+
+process.versions.node.split('.')[0] < 20,
147+
)('cases', async () => {
148+
await loadWasm(import('@shikijs/core/wasm-inlined'))
149+
148150
const resolved = await Promise.all(cases.map(async (c) => {
149151
const theme = await c.theme().then(r => r.default)
150152
const lang = await c.lang().then(r => r.default)
@@ -159,7 +161,10 @@ describe('cases', async () => {
159161
const run = c.c.skip ? it.skip : it
160162
run(c.c.name, async () => {
161163
const engineWasm = createWasmOnigLibWrapper()
162-
const engineJs = createJavaScriptRegexEngine()
164+
const engineJs = createJavaScriptRegexEngine({
165+
forgiving: true,
166+
target: 'ES2024',
167+
})
163168

164169
const shiki1 = await createHighlighterCore({
165170
langs: c.lang,
@@ -188,11 +193,11 @@ describe('cases', async () => {
188193
.soft(JSON.stringify(engineWasm.instances, null, 2))
189194
.toMatchFileSnapshot(`./__records__/${c.c.name}.json`)
190195

191-
compare.forEach(([a, b]) => {
192-
expect.soft(a).toEqual(b)
193-
// await expect.soft(a)
194-
// .toMatchFileSnapshot(`./__records__/tokens/${c.c.name}-${i}.json`)
195-
})
196+
// compare.forEach(([a, b]) => {
197+
// expect.soft(a).toEqual(b)
198+
// // await expect.soft(a)
199+
// // .toMatchFileSnapshot(`./__records__/tokens/${c.c.name}-${i}.json`)
200+
// })
196201
})
197202
}
198203
})

Diff for: ‎packages/engine-javascript/test/general.test.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import { createHighlighter } from '../../shiki/src/index'
33
import { createJavaScriptRegexEngine } from '../src'
44

5-
describe('should', () => {
5+
describe.skipIf(
6+
+process.versions.node.split('.')[0] < 20,
7+
)('should', () => {
68
it('works', async () => {
79
const shiki = await createHighlighter({
810
themes: ['vitesse-light'],
@@ -11,7 +13,7 @@
1113
})
1214

1315
expect(shiki.codeToHtml('console.log', { lang: 'js', theme: 'vitesse-light' }))
1416
.toMatchInlineSnapshot(`"<pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0"><code><span class="line"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#B07D48">log</span></span></code></pre>"`)
1517
})
1618

1719
it('dynamic load theme and lang', async () => {

Diff for: ‎packages/engine-javascript/test/utils.test.ts

-28
This file was deleted.

Diff for: ‎packages/engine-javascript/test/verify.test.ts

+52-45
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,60 @@ import fg from 'fast-glob'
66
import { describe, expect, it, onTestFailed } from 'vitest'
77
import { JavaScriptScanner } from '../src'
88

9-
const files = await fg('*.json', {
10-
cwd: fileURLToPath(new URL('./__records__', import.meta.url)),
11-
absolute: true,
12-
onlyFiles: true,
13-
})
9+
describe('verify', async () => {
10+
if (+process.versions.node.split('.')[0] < 20) {
11+
it('skip', () => {})
12+
return
13+
}
14+
15+
const files = await fg('*.json', {
16+
cwd: fileURLToPath(new URL('./__records__', import.meta.url)),
17+
absolute: true,
18+
onlyFiles: true,
19+
})
1420

15-
const cache = new Map<string, RegExp | Error>()
21+
const cache = new Map<string, RegExp | Error>()
1622

17-
for (const file of files) {
18-
// Some token positions are off in this record
19-
const name = basename(file, '.json')
23+
for (const file of files) {
24+
// Some token positions are off in this record
25+
const name = basename(file, '.json')
2026

21-
// TODO: markdown support is still problematic
22-
if (name === 'markdown')
23-
continue
27+
// TODO: markdown support is still problematic
28+
if (name === 'markdown')
29+
continue
2430

25-
describe(`record: ${name}`, async () => {
26-
const instances = JSON.parse(await fs.readFile(file, 'utf-8')) as Instance[]
27-
let i = 0
28-
for (const instance of instances) {
29-
i += 1
30-
describe(`instances ${i}`, () => {
31-
const scanner = new JavaScriptScanner(instance.constractor[0], { cache })
32-
let j = 0
33-
for (const execution of instance.executions) {
34-
j += 1
35-
it(`case ${j}`, () => {
36-
onTestFailed(() => {
37-
console.error(execution.result?.index != null
38-
? {
39-
args: execution.args,
40-
expected: {
41-
pattern: scanner.patterns[execution.result.index],
42-
regexp: scanner.regexps[execution.result.index],
43-
},
44-
}
45-
: {
46-
args: execution.args,
47-
patterns: scanner.patterns,
48-
regexps: scanner.regexps,
49-
})
31+
describe(`record: ${name}`, async () => {
32+
const instances = JSON.parse(await fs.readFile(file, 'utf-8')) as Instance[]
33+
let i = 0
34+
for (const instance of instances) {
35+
i += 1
36+
describe(`instances ${i}`, () => {
37+
const scanner = new JavaScriptScanner(instance.constractor[0], { cache })
38+
let j = 0
39+
for (const execution of instance.executions) {
40+
j += 1
41+
it(`case ${j}`, () => {
42+
onTestFailed(() => {
43+
console.error(execution.result?.index != null
44+
? {
45+
args: execution.args,
46+
expected: {
47+
pattern: scanner.patterns[execution.result.index],
48+
regexp: scanner.regexps[execution.result.index],
49+
},
50+
}
51+
: {
52+
args: execution.args,
53+
patterns: scanner.patterns,
54+
regexps: scanner.regexps,
55+
})
56+
})
57+
const result = scanner.findNextMatchSync(...execution.args)
58+
expect(result).toEqual(execution.result)
5059
})
51-
const result = scanner.findNextMatchSync(...execution.args)
52-
expect(result).toEqual(execution.result)
53-
})
54-
}
55-
})
56-
}
57-
})
58-
}
60+
}
61+
})
62+
}
63+
})
64+
}
65+
})

Diff for: ‎packages/shiki/test/core-sync.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { createHighlighterCoreSync } from '../src/core'
44
import js from '../src/langs/javascript.mjs'
55
import nord from '../src/themes/nord.mjs'
66

7-
describe('should', () => {
7+
describe.skipIf(
8+
// JavaScript engine requires Node v20+
9+
+process.versions.node.split('.')[0] < 20,
10+
)('should', () => {
811
const engine = createJavaScriptRegexEngine()
912

1013
it('works', () => {

Diff for: ‎pnpm-lock.yaml

+35-198
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎pnpm-workspace.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ catalog:
5353
minimist: ^1.2.8
5454
monaco-editor-core: ^0.52.0
5555
ofetch: ^1.4.1
56-
oniguruma-to-js: 0.4.3
56+
oniguruma-to-es: 0.1.2
5757
picocolors: ^1.1.1
5858
pinia: ^2.2.4
5959
pnpm: ^9.12.3

Diff for: ‎scripts/report-engine-js-compat.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ import { format } from 'prettier'
1212
import { bundledLanguages, createHighlighter, createJavaScriptRegexEngine } from 'shiki'
1313
import { version } from '../package.json'
1414

15-
const engine = createJavaScriptRegexEngine()
15+
const engine = createJavaScriptRegexEngine({
16+
target: 'ES2024',
17+
})
1618
const engineForgiving = createJavaScriptRegexEngine({
19+
target: 'ES2024',
1720
forgiving: true,
1821
})
1922

@@ -219,27 +222,27 @@ async function run() {
219222
'',
220223
'## Supported Languages',
221224
'',
222-
'Languages that works with the JavaScript RegExp engine, and will produce the same result as the WASM engine (with the [sample snippets in the registry](https://github.com/shikijs/textmate-grammars-themes/tree/main/samples)).',
223-
'In some edge cases, it\'s not guaranteed that the the highlight will be 100% the same. If that happens, please create an issue with the sample snippet.',
225+
'Languages that work with the JavaScript RegExp engine, and will produce the same result as the WASM engine (with the [sample snippets in the registry](https://github.com/shikijs/textmate-grammars-themes/tree/main/samples)).',
226+
'In some edge cases, it\'s not guaranteed that the the highlighting will be 100% the same. If that happens, please create an issue with the sample snippet.',
224227
'',
225228
createTable(reportOk),
226229
'',
227230
'###### Table Field Explanations',
228231
'',
229-
'- **Highlight Match**: Highlight results match with the WASM engine with the [sample snippets](https://github.com/shikijs/textmate-grammars-themes/tree/main/samples).',
232+
'- **Highlight Match**: Whether the highlighting results matched with the WASM engine for the [sample snippet](https://github.com/shikijs/textmate-grammars-themes/tree/main/samples).',
230233
'- **Patterns Parsable**: Number of regex patterns that can be parsed by the JavaScript RegExp engine.',
231234
'- **Patterns Failed**: Number of regex patterns that can\'t be parsed by the JavaScript RegExp engine (throws error).',
232-
'- **Diff**: Length of characters that are different between the highlight result of two engines.',
235+
'- **Diff**: Length of characters that are different between the highlighting results of the two engines.',
233236
'',
234237
'## Mismatched Languages',
235238
'',
236-
'Languages that does not throw with the JavaScript RegExp engine, but will produce different result than the WASM engine. Please use with caution.',
239+
'Languages that do not throw with the JavaScript RegExp engine, but will produce different results than the WASM engine. Please use with caution.',
237240
'',
238241
createTable(reportMismatch),
239242
'',
240243
'## Unsupported Languages',
241244
'',
242-
'Languages that throws with the JavaScript RegExp engine (contains syntaxes that we can\'t polyfill yet). If you need to use these languages, please use the Oniguruma engine.',
245+
'Languages that throw with the JavaScript RegExp engine, either because they contain syntax we can\'t polyfill yet or because the grammar contains an invalid Oniguruma regex (that would also fail when using the WASM engine, but silently). You can try these languages with the `forgiving` option to skip errors, but usually it\'s best to use the Oniguruma engine instead.',
243246
'',
244247
createTable(reportError),
245248
].join('\n')

Diff for: ‎vitest.config.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import tsconfigPaths from 'vite-tsconfig-paths'
44
import { defineConfig } from 'vitest/config'
55
import { wasmPlugin } from './packages/core/rollup.config.mjs'
66

7-
const localOnigurumaToJs = fileURLToPath(new URL('../oniguruma-to-js/src/index.ts', import.meta.url))
7+
const localOnigurumaToEs = fileURLToPath(new URL('../oniguruma-to-es/dist/index.mjs', import.meta.url))
88

99
export default defineConfig({
1010
resolve: {
1111
alias: {
1212
// For local developement
13-
...existsSync(localOnigurumaToJs)
13+
...existsSync(localOnigurumaToEs)
1414
? {
15-
'oniguruma-to-js': localOnigurumaToJs,
15+
'oniguruma-to-es': localOnigurumaToEs,
1616
}
1717
: {},
1818
},

0 commit comments

Comments
 (0)
Please sign in to comment.