diff --git a/README.md b/README.md index 62e2b87..0d01ff1 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,9 @@ type OnigurumaToEsOptions = { maxRecursionDepth?: number | null; rules?: { allowOrphanBackrefs?: boolean; - allowUnhandledGAnchors?: boolean; asciiWordBoundaries?: boolean; captureGroup?: boolean; + ignoreUnsupportedGAnchors?: boolean; }; target?: 'auto' | 'ES2025' | 'ES2024' | 'ES2018'; verbose?: boolean; @@ -217,10 +217,10 @@ Using a high limit has a small impact on performance. Generally, this is only a Advanced pattern options that override standard error checking and flags when enabled. - `allowOrphanBackrefs`: Useful with TextMate grammars that merge backreferences across patterns. -- `allowUnhandledGAnchors`: Removes unsupported uses of `\G`, rather than erroring. - - Oniguruma-To-ES uses a variety of strategies to accurately emulate many common uses of `\G`. When using this option, if a `\G` is found that doesn't have a known emulation strategy, the `\G` is simply removed. This might lead to some false positive matches, but is useful for non-critical matching (like syntax highlighting) when having some mismatches is better than not working. - `asciiWordBoundaries`: Use ASCII-based `\b` and `\B`, which increases search performance of generated regexes. - `captureGroup`: Oniguruma option `ONIG_OPTION_CAPTURE_GROUP`. Unnamed captures and numbered calls allowed when using named capture. +- `ignoreUnsupportedGAnchors`: Removes unsupported uses of `\G`, rather than erroring. + - Oniguruma-To-ES uses a variety of strategies to accurately emulate many common uses of `\G`. When using this option, if a `\G` is found that doesn't have a known emulation strategy, the `\G` is simply removed. This might lead to some false positive matches, but is useful for non-critical matching (like syntax highlighting) when having some mismatches is better than not working. ### `target` diff --git a/demo/demo.js b/demo/demo.js index 828b0e2..3f79c67 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -22,9 +22,9 @@ const state = { maxRecursionDepth: getValue('option-maxRecursionDepth'), rules: { allowOrphanBackrefs: getValue('option-allowOrphanBackrefs'), - allowUnhandledGAnchors: getValue('option-allowUnhandledGAnchors'), asciiWordBoundaries: getValue('option-asciiWordBoundaries'), captureGroup: getValue('option-captureGroup'), + ignoreUnsupportedGAnchors: getValue('option-ignoreUnsupportedGAnchors'), }, target: getValue('option-target'), verbose: getValue('option-verbose'), diff --git a/demo/index.html b/demo/index.html index 6db978f..fdbf163 100644 --- a/demo/index.html +++ b/demo/index.html @@ -118,8 +118,8 @@

Try it

diff --git a/spec/match-search-start.spec.js b/spec/match-search-start.spec.js index 73dd5b0..975d5b5 100644 --- a/spec/match-search-start.spec.js +++ b/spec/match-search-start.spec.js @@ -135,7 +135,7 @@ describe('Assertion: Search start', () => { ]; patterns.forEach(pattern => { expect(() => toDetails(pattern)).toThrow(); - expect(() => toDetails(pattern, {rules: {allowUnhandledGAnchors: true}})).not.toThrow(); + expect(() => toDetails(pattern, {rules: {ignoreUnsupportedGAnchors: true}})).not.toThrow(); }); }); }); diff --git a/src/index.js b/src/index.js index a91206d..7b8169c 100644 --- a/src/index.js +++ b/src/index.js @@ -30,9 +30,9 @@ import {recursion} from 'regex-recursion'; maxRecursionDepth?: number | null; rules?: { allowOrphanBackrefs?: boolean; - allowUnhandledGAnchors?: boolean; asciiWordBoundaries?: boolean; captureGroup?: boolean; + ignoreUnsupportedGAnchors?: boolean; }; target?: keyof Target; verbose?: boolean; @@ -59,10 +59,10 @@ function toDetails(pattern, options) { }); const regexAst = transform(onigurumaAst, { accuracy: opts.accuracy, - allowUnhandledGAnchors: opts.rules.allowUnhandledGAnchors, asciiWordBoundaries: opts.rules.asciiWordBoundaries, avoidSubclass, bestEffortTarget: opts.target, + ignoreUnsupportedGAnchors: opts.rules.ignoreUnsupportedGAnchors, }); const generated = generate(regexAst, opts); const pluginData = {useEmulationGroups: !avoidSubclass}; diff --git a/src/options.js b/src/options.js index b866de0..7f84232 100644 --- a/src/options.js +++ b/src/options.js @@ -55,13 +55,13 @@ function getOptions(options) { rules: { // Useful with TextMate grammars that merge backreferences across patterns. allowOrphanBackrefs: false, - // Removes unsupported uses of `\G`, rather than erroring. - allowUnhandledGAnchors: false, // Use ASCII-based `\b` and `\B`, which increases search performance of generated regexes. asciiWordBoundaries: false, // Oniguruma option `ONIG_OPTION_CAPTURE_GROUP`. Unnamed captures and numbered calls allowed // when using named capture. captureGroup: false, + // Removes unsupported uses of `\G`, rather than erroring. + ignoreUnsupportedGAnchors: false, ...(options?.rules), }, }; diff --git a/src/transform.js b/src/transform.js index fe9e956..390220e 100644 --- a/src/transform.js +++ b/src/transform.js @@ -30,10 +30,10 @@ AST represents what's needed to precisely reproduce Oniguruma behavior using Reg @param {import('./parse.js').OnigurumaAst} ast @param {{ accuracy?: keyof Accuracy; - allowUnhandledGAnchors?: boolean; asciiWordBoundaries?: boolean; avoidSubclass?: boolean; bestEffortTarget?: keyof Target; + ignoreUnsupportedGAnchors?: boolean; }} [options] @returns {RegexAst} */ @@ -46,19 +46,19 @@ function transform(ast, options) { // representations would be hard to change to ASCII-based after the fact in the generator // based on `target`/`accuracy`, so produce the appropriate structure here. accuracy: 'default', - allowUnhandledGAnchors: false, asciiWordBoundaries: false, avoidSubclass: false, bestEffortTarget: 'ES2025', + ignoreUnsupportedGAnchors: false, ...options, }; // AST transformations that work together with a `RegExp` subclass to add advanced emulation const strategy = opts.avoidSubclass ? null : applySubclassStrategies(ast); const firstPassState = { accuracy: opts.accuracy, - allowUnhandledGAnchors: opts.allowUnhandledGAnchors, asciiWordBoundaries: opts.asciiWordBoundaries, flagDirectivesByAlt: new Map(), + ignoreUnsupportedGAnchors: opts.ignoreUnsupportedGAnchors, minTargetEs2024: isMinTarget(opts.bestEffortTarget, 'ES2024'), // Subroutines can appear before the groups they ref, so collect reffed nodes for a second pass subroutineRefMap: new Map(), @@ -130,7 +130,7 @@ const FirstPassVisitor = { }, }, - Assertion({node, ast, remove, replaceWith}, {allowUnhandledGAnchors, asciiWordBoundaries, supportedGNodes, wordIsAscii}) { + Assertion({node, ast, remove, replaceWith}, {asciiWordBoundaries, ignoreUnsupportedGAnchors, supportedGNodes, wordIsAscii}) { const {kind, negate} = node; if (kind === AstAssertionKinds.line_end) { // Onig's only line break char is line feed, unlike JS @@ -142,7 +142,7 @@ const FirstPassVisitor = { } else if (kind === AstAssertionKinds.search_start) { if (supportedGNodes.has(node)) { ast.flags.sticky = true; - } else if (!allowUnhandledGAnchors) { + } else if (!ignoreUnsupportedGAnchors) { throw new Error(r`Uses "\G" in a way that's unsupported`); } remove(); @@ -305,7 +305,7 @@ const FirstPassVisitor = { !node.flags.enable && !node.flags.disable && delete node.flags; }, - Pattern({node}, {allowUnhandledGAnchors, supportedGNodes}) { + Pattern({node}, {ignoreUnsupportedGAnchors, supportedGNodes}) { // For `\G` to be accurately emulatable using JS flag y, it must be at (and only at) the start // of every top-level alternative (with complex rules for what determines being at the start). // Additional `\G` error checking in `Assertion` visitor @@ -327,7 +327,7 @@ const FirstPassVisitor = { if (!hasAltWithoutLeadG) { // Supported `\G` nodes will be removed (and add flag y) when traversed; others will error leadingGs.forEach(g => supportedGNodes.add(g)); - } else if (!allowUnhandledGAnchors) { + } else if (!ignoreUnsupportedGAnchors) { throw new Error(r`Uses "\G" in a way that's unsupported`); } }