Skip to content

Commit

Permalink
Change overrides to rules
Browse files Browse the repository at this point in the history
  • Loading branch information
slevithan committed Nov 22, 2024
1 parent 351a875 commit ea8846e
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 35 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ type OnigurumaToEsOptions = {
global?: boolean;
hasIndices?: boolean;
maxRecursionDepth?: number | null;
overrides?: {
allowAllSearchStartAnchors?: boolean;
rules?: {
allowOrphanBackrefs?: boolean;
allowUnhandledGAnchors?: boolean;
asciiWordBoundaries?: boolean;
};
target?: 'auto' | 'ES2025' | 'ES2024' | 'ES2018';
Expand Down Expand Up @@ -203,13 +203,13 @@ Since recursion isn't infinite-depth like in Oniguruma, use of recursion also re
Using a high limit has a small impact on performance. Generally, this is only a problem if the regex has an existing issue with runaway backtracking that recursion exacerbates. Higher limits have no effect on regexes that don't use recursion, so you should feel free to increase this if helpful.
</details>

### `overrides`
### `rules`

Advanced options that take precedence over standard error checking and flags when enabled.
Advanced pattern options that override standard error checking and flags when enabled.

- `allowAllSearchStartAnchors`: Silences errors for unsupported uses of the search-start anchor `\G`.
- 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 and JavaScript's `y` (`sticky`) flag is added. This might lead to some false positives and negatives, but is useful for non-critical matching (like syntax highlighting) when having some mismatches is better than not working.
- `allowOrphanBackrefs`: Useful with TextMate grammars that merge backreferences across patterns.
- `allowUnhandledGAnchors`: Applies flag `y` for 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 and JavaScript's `y` (`sticky`) flag is added. This might lead to some false positives and negatives, but is useful for non-critical matching (like syntax highlighting) when having some mismatches is better than not working.
- `asciiWordBoundaries`: ASCII-based `\b` and `\B`.

### `target`
Expand Down
8 changes: 4 additions & 4 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ const state = {
global: getValue('option-global'),
hasIndices: getValue('option-hasIndices'),
maxRecursionDepth: getValue('option-maxRecursionDepth'),
overrides: {
allowAllSearchStartAnchors: getValue('option-allowAllSearchStartAnchors'),
rules: {
allowOrphanBackrefs: getValue('option-allowOrphanBackrefs'),
allowUnhandledGAnchors: getValue('option-allowUnhandledGAnchors'),
asciiWordBoundaries: getValue('option-asciiWordBoundaries'),
},
target: getValue('option-target'),
Expand Down Expand Up @@ -224,7 +224,7 @@ function setOption(option, value) {
showTranspiled();
}

function setOverride(option, value) {
state.opts.overrides[option] = value;
function setRule(rule, value) {
state.opts.rules[rule] = value;
showTranspiled();
}
14 changes: 7 additions & 7 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,23 @@ <h2>Try it</h2>
<div>
<p>
<label>
<input type="checkbox" id="option-allowAllSearchStartAnchors" onchange="setOverride('allowAllSearchStartAnchors', this.checked)">
<code>allowAllSearchStartAnchors</code>
<span class="tip tip-lg">Silences errors for unsupported uses of <code>\G</code></span>
<input type="checkbox" id="option-allowOrphanBackrefs" onchange="setRule('allowOrphanBackrefs', this.checked)">
<code>allowOrphanBackrefs</code>
<span class="tip tip-xl">Useful with TextMate grammars that merge backrefs across <code>begin</code> and <code>end</code> patterns</span>
</label>
</p>
<p>
<label>
<input type="checkbox" id="option-allowOrphanBackrefs" onchange="setOverride('allowOrphanBackrefs', this.checked)">
<code>allowOrphanBackrefs</code>
<span class="tip tip-xl">Useful with TextMate grammars that merge backrefs across <code>begin</code> and <code>end</code> patterns</span>
<input type="checkbox" id="option-allowUnhandledGAnchors" onchange="setRule('allowUnhandledGAnchors', this.checked)">
<code>allowUnhandledGAnchors</code>
<span class="tip tip-xl">Applies flag <code>y</code> for unsupported uses of <code>\G</code>, rather than erroring</span>
</label>
</p>
</div>
<div>
<p>
<label>
<input type="checkbox" id="option-asciiWordBoundaries" onchange="setOverride('asciiWordBoundaries', this.checked)">
<input type="checkbox" id="option-asciiWordBoundaries" onchange="setRule('asciiWordBoundaries', this.checked)">
<code>asciiWordBoundaries</code>
<span class="tip tip-lg">ASCII-based <code>\b</code> and <code>\B</code></span>
</label>
Expand Down
2 changes: 1 addition & 1 deletion spec/match-search-start.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('Assertion: Search start', () => {
];
patterns.forEach(pattern => {
expect(() => toDetails(pattern)).toThrow();
expect(toRegExp(pattern, {overrides: {allowAllSearchStartAnchors: true}}).sticky).toBe(true);
expect(toRegExp(pattern, {rules: {allowUnhandledGAnchors: true}}).sticky).toBe(true);
});
});
});
Expand Down
10 changes: 5 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import {recursion} from 'regex-recursion';
global?: boolean;
hasIndices?: boolean;
maxRecursionDepth?: number | null;
overrides?: {
allowAllSearchStartAnchors?: boolean;
rules?: {
allowOrphanBackrefs?: boolean;
allowUnhandledGAnchors?: boolean;
asciiWordBoundaries?: boolean;
};
target?: keyof Target;
Expand All @@ -52,13 +52,13 @@ function toDetails(pattern, options) {
const opts = getOptions(options);
const tokenized = tokenize(pattern, opts.flags);
const onigurumaAst = parse(tokenized, {
skipBackrefValidation: opts.overrides.allowOrphanBackrefs,
skipBackrefValidation: opts.rules.allowOrphanBackrefs,
verbose: opts.verbose,
});
const regexAst = transform(onigurumaAst, {
accuracy: opts.accuracy,
allowAllSearchStartAnchors: opts.overrides.allowAllSearchStartAnchors,
asciiWordBoundaries: opts.overrides.asciiWordBoundaries,
allowUnhandledGAnchors: opts.rules.allowUnhandledGAnchors,
asciiWordBoundaries: opts.rules.asciiWordBoundaries,
avoidSubclass: opts.avoidSubclass,
bestEffortTarget: opts.target,
});
Expand Down
10 changes: 5 additions & 5 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ function getOptions(options) {
// Disables optimizations that simplify the pattern when it doesn't change the meaning.
verbose: false,
...options,
// Advanced options that take precedence over standard error checking and flags when enabled.
overrides: {
// Silences errors for unsupported uses of the search-start anchor `\G`.
allowAllSearchStartAnchors: false,
// Advanced pattern options that override standard error checking and flags when enabled.
rules: {
// Useful with TextMate grammars that merge backreferences across patterns.
allowOrphanBackrefs: false,
// Applies flag `y` for unsupported uses of `\G`, rather than erroring.
allowUnhandledGAnchors: false,
// ASCII-based `\b` and `\B`.
asciiWordBoundaries: false,
...(options?.overrides),
...(options?.rules),
},
};
if (opts.target === 'auto') {
Expand Down
14 changes: 7 additions & 7 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ AST represents what's needed to precisely reproduce Oniguruma behavior using Reg
@param {import('./parse.js').OnigurumaAst} ast
@param {{
accuracy?: keyof Accuracy;
allowAllSearchStartAnchors?: boolean;
allowUnhandledGAnchors?: boolean;
asciiWordBoundaries?: boolean;
avoidSubclass?: boolean;
bestEffortTarget?: keyof Target;
Expand All @@ -46,7 +46,7 @@ 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',
allowAllSearchStartAnchors: false,
allowUnhandledGAnchors: false,
asciiWordBoundaries: false,
avoidSubclass: false,
bestEffortTarget: 'ES2025',
Expand All @@ -56,7 +56,7 @@ function transform(ast, options) {
const strategy = opts.avoidSubclass ? null : applySubclassStrategies(ast);
const firstPassState = {
accuracy: opts.accuracy,
allowAllSearchStartAnchors: opts.allowAllSearchStartAnchors,
allowUnhandledGAnchors: opts.allowUnhandledGAnchors,
asciiWordBoundaries: opts.asciiWordBoundaries,
flagDirectivesByAlt: new Map(),
minTargetEs2024: isMinTarget(opts.bestEffortTarget, 'ES2024'),
Expand Down Expand Up @@ -130,7 +130,7 @@ const FirstPassVisitor = {
},
},

Assertion({node, ast, remove, replaceWith}, {allowAllSearchStartAnchors, asciiWordBoundaries, supportedGNodes, wordIsAscii}) {
Assertion({node, ast, remove, replaceWith}, {allowUnhandledGAnchors, asciiWordBoundaries, supportedGNodes, wordIsAscii}) {
const {kind, negate} = node;
if (kind === AstAssertionKinds.line_end) {
// Onig's only line break char is line feed, unlike JS
Expand All @@ -139,7 +139,7 @@ const FirstPassVisitor = {
// Onig's only line break char is line feed, unlike JS
replaceWith(parseFragment(r`(?<=\A|\n)`));
} else if (kind === AstAssertionKinds.search_start) {
if (!supportedGNodes.has(node) && !allowAllSearchStartAnchors) {
if (!supportedGNodes.has(node) && !allowUnhandledGAnchors) {
throw new Error(r`Uses "\G" in a way that's unsupported`);
}
ast.flags.sticky = true;
Expand Down Expand Up @@ -300,7 +300,7 @@ const FirstPassVisitor = {
!node.flags.enable && !node.flags.disable && delete node.flags;
},

Pattern({node}, {allowAllSearchStartAnchors, supportedGNodes}) {
Pattern({node}, {allowUnhandledGAnchors, 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
Expand All @@ -318,7 +318,7 @@ const FirstPassVisitor = {
hasAltWithoutLeadG = true;
}
}
if (hasAltWithLeadG && hasAltWithoutLeadG && !allowAllSearchStartAnchors) {
if (hasAltWithLeadG && hasAltWithoutLeadG && !allowUnhandledGAnchors) {
throw new Error(r`Uses "\G" in a way that's unsupported`);
}
// Supported `\G` nodes will be removed when traversed; others will error
Expand Down

0 comments on commit ea8846e

Please sign in to comment.