@ptolemy2002/rgx 7.0.0 → 7.2.0
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/README.md +16 -3
- package/dist/class/repeat.js +1 -1
- package/dist/constants.js +9 -0
- package/dist/flag-transformer/accentInsensitive.js +4 -1
- package/dist/walker/base.d.ts +4 -0
- package/dist/walker/base.js +19 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -100,6 +100,8 @@ type RGXPartOptions<R, T=string> = {
|
|
|
100
100
|
type RGXWalkerOptions<R> = {
|
|
101
101
|
startingSourcePosition?: number;
|
|
102
102
|
reduced?: R;
|
|
103
|
+
infinite?: boolean;
|
|
104
|
+
looping?: boolean;
|
|
103
105
|
};
|
|
104
106
|
|
|
105
107
|
type RGXWOptions<R = unknown> = Omit<RGXWalkerOptions<R>, "startingSourcePosition"> & {
|
|
@@ -657,6 +659,8 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
657
659
|
- `options` (`RGXWalkerOptions<R>`, optional): Configuration options. Defaults to `{}`.
|
|
658
660
|
- `startingSourcePosition` (`number`, optional): The starting index in the source string. Defaults to `0`.
|
|
659
661
|
- `reduced` (`R`, optional): The initial value for the `reduced` accumulator. Defaults to `null`.
|
|
662
|
+
- `infinite` (`boolean`, optional): When `true`, the walker stays at the last token indefinitely rather than stopping when the token collection is exhausted, continuing to match the last token until the source is consumed. Defaults to `false`.
|
|
663
|
+
- `looping` (`boolean`, optional): When `true`, the walker loops back to token position `0` when the token collection is exhausted, continuing to match from the start until the source is consumed. Defaults to `false`.
|
|
660
664
|
|
|
661
665
|
#### Properties
|
|
662
666
|
- `source` (`string`): The source string being walked (readonly).
|
|
@@ -666,6 +670,8 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
666
670
|
- `reduced` (`R`): A user-defined accumulator value, typically updated by `RGXPart` callbacks during walking.
|
|
667
671
|
- `captures` (`RGXCapture[]`): An array of structured capture results recorded during walking. Each entry has a `raw` string, a `value` (the transform result for Parts, or the raw string for plain tokens), `start` and `end` indices in the source string, and an `ownerId` that is the `id` of the Part that produced it (or `null` for captures from plain tokens or parts without ids).
|
|
668
672
|
- `namedCaptures` (`Record<string, RGXCapture[]>`): An object mapping capture IDs to their corresponding `RGXCapture` results. Only Parts with non-null IDs are included. The captures occur in the same order as they appear in the `captures` array.
|
|
673
|
+
- `infinite` (`boolean`): Whether the walker is in infinite mode — stays at the last token when the token collection is exhausted until the source is consumed.
|
|
674
|
+
- `looping` (`boolean`): Whether the walker is in looping mode — loops back to token position `0` when the token collection is exhausted until the source is consumed.
|
|
669
675
|
- `stopped` (`boolean`, readonly): Whether the walker has been stopped, either by a Part's `beforeCapture` returning `"stop"` or by calling `stop()` in an `afterCapture` callback.
|
|
670
676
|
|
|
671
677
|
#### Methods
|
|
@@ -678,12 +684,12 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
678
684
|
- `currentToken() => RGXToken | null`: Returns the token at the current token position, or `null` if at the end.
|
|
679
685
|
- `remainingSource() => string | null`: Returns the remaining source string from the current position onward, or `null` if the source is fully consumed.
|
|
680
686
|
- `capture(token: RGXToken) => string`: Resolves the token to a regex, asserts that it matches at the current source position (throwing `RGXRegexNotMatchedAtPositionError` if not), and advances the source position by the match length. Returns the matched string.
|
|
681
|
-
- `step() => RGXCapture | null`: Steps through the next token in the collection. If the token is an `RGXPart`, calls `beforeCapture` first — if it returns `"stop"`, sets `stopped` and returns `null` without advancing; if `"skip"`, advances the token position and returns `null` without capturing; if `"silent"`, captures but does not add to `captures` or `namedCaptures`. After capturing, validates. After validating, calls `afterCapture` if present. Returns the `RGXCapture` result, or `null` if there are no more tokens, the step was skipped, or the walker was stopped.
|
|
687
|
+
- `step() => RGXCapture | null`: Steps through the next token in the collection. If the token is an `RGXPart`, calls `beforeCapture` first — if it returns `"stop"`, sets `stopped` and returns `null` without advancing; if `"skip"`, advances the token position and returns `null` without capturing; if `"silent"`, captures but does not add to `captures` or `namedCaptures`. After capturing, validates. After validating, calls `afterCapture` if present. Returns the `RGXCapture` result, or `null` if there are no more tokens (or no more source in `infinite`/`looping` mode), the step was skipped, or the walker was stopped.
|
|
682
688
|
- `stepToToken(predicate: (token: RGXToken) => boolean) => void`: Steps through tokens until the predicate returns `true` for the current token or the walker is stopped. The matching token is not consumed.
|
|
683
689
|
- `stepToPart(predicate?: (part: RGXPart<R>) => boolean) => void`: Steps through tokens until the next `RGXPart` satisfying the predicate is reached. If already at a Part, steps once first to move past it. The matching Part is not consumed.
|
|
684
|
-
- `walk() => void`: Steps through all remaining tokens until the end of the token collection or the walker is stopped.
|
|
690
|
+
- `walk() => void`: Steps through all remaining tokens until the end of the token collection (or until the source is consumed in `infinite`/`looping` mode) or the walker is stopped.
|
|
685
691
|
- `toRgx() => RGXToken`: Returns the internal `RGXTokenCollection`, allowing the walker to be used as a convertible token.
|
|
686
|
-
- `clone(depth: CloneDepth = "max") => RGXWalker`: Creates a clone of the walker. When `depth` is `0`, returns `this`; otherwise, creates a new `RGXWalker` with cloned tokens, source position, reduced value, captures, and
|
|
692
|
+
- `clone(depth: CloneDepth = "max") => RGXWalker`: Creates a clone of the walker. When `depth` is `0`, returns `this`; otherwise, creates a new `RGXWalker` with cloned tokens, source position, reduced value, captures, stopped state, and the `infinite`/`looping` flags.
|
|
687
693
|
|
|
688
694
|
## Functions
|
|
689
695
|
The following functions are exported by the library:
|
|
@@ -1354,6 +1360,8 @@ A pre-built `RegExpFlagTransformer` that makes a regex pattern accent-insensitiv
|
|
|
1354
1360
|
- `o` / `O`: ó, ò, ö, ô, õ / Ó, Ò, Ö, Ô, Õ
|
|
1355
1361
|
- `u` / `U`: ú, ù, ü, û / Ú, Ù, Ü, Û
|
|
1356
1362
|
|
|
1363
|
+
Note that this transformer intentionally excludes replacing characters preceded by an odd number of backslashes, to allow for escaping. For example, in the pattern `\\a`, the `a` is preceded by two backslashes (an even number), so it will be replaced with `(a|á|à|ä|â|ã)`. In the pattern `\a`, the `a` is preceded by one backslash (an odd number), so it will not be replaced.
|
|
1364
|
+
|
|
1357
1365
|
#### Parameters
|
|
1358
1366
|
- `exp` (`RegExp`): The regular expression to transform.
|
|
1359
1367
|
|
|
@@ -1660,6 +1668,11 @@ Since these are defined as native tokens (strings), they are automatically wrapp
|
|
|
1660
1668
|
| `"non-word-char"` | `\W` | Any non-word character |
|
|
1661
1669
|
| `"backspace"` | `[\b]` | Backspace character |
|
|
1662
1670
|
|
|
1671
|
+
### Complex Constructs
|
|
1672
|
+
| Name | Resolves To | Description |
|
|
1673
|
+
| --- | --- | --- |
|
|
1674
|
+
| `"non-escape-bound"` | `(?<=(?<!\\)(?:\\\\)*)(?=[^\\]\|$)` | Matches a position that is not preceded by an odd number of backslashes, i.e., the next character is not escaped. Note that this doesn't match when the next character is a backslash, since allowing it to do that would cause non-escaped backslashes within a series of backslashes to be treated as escaped. For example, in the string `\\\a`, the first and third backslashes would be treated as escaped. |
|
|
1675
|
+
|
|
1663
1676
|
## Peer Dependencies
|
|
1664
1677
|
- `@ptolemy2002/immutability-utils` ^2.0.0
|
|
1665
1678
|
- `@ptolemy2002/js-utils` ^3.2.2
|
package/dist/class/repeat.js
CHANGED
|
@@ -32,7 +32,7 @@ class RGXRepeatToken extends base_1.RGXClassToken {
|
|
|
32
32
|
return this._token;
|
|
33
33
|
}
|
|
34
34
|
set token(value) {
|
|
35
|
-
if ((0, typeGuards_1.isRGXToken)(value, "convertible") && !value.rgxIsRepeatable) {
|
|
35
|
+
if ((0, typeGuards_1.isRGXToken)(value, "convertible") && typeof value.rgxIsRepeatable === "boolean" && !value.rgxIsRepeatable) {
|
|
36
36
|
if ((0, typeGuards_1.isRGXToken)(value, "class")) {
|
|
37
37
|
throw new errors_1.RGXNotSupportedError(`Repeating ${value.constructor.name} tokens`, "The token was manually marked as non-repeatable.");
|
|
38
38
|
}
|
package/dist/constants.js
CHANGED
|
@@ -191,3 +191,12 @@ defineRGXConstant("backspace", {
|
|
|
191
191
|
return /[\b]/;
|
|
192
192
|
}
|
|
193
193
|
});
|
|
194
|
+
// Complex Constructs
|
|
195
|
+
// Put this before any pattern to ensure that the pattern is not escaped, i.e., not preceded by an odd number of backslashes.
|
|
196
|
+
defineRGXConstant("non-escape-bound", {
|
|
197
|
+
rgxGroupWrap: false,
|
|
198
|
+
rgxIsRepeatable: false,
|
|
199
|
+
toRgx() {
|
|
200
|
+
return /(?<=(?<!\\)(?:\\\\)*)(?=[^\\]|$)/;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.accentInsensitiveFlagTransformer = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const resolve_1 = require("../resolve");
|
|
4
6
|
const accentPatterns = [
|
|
5
7
|
"(a|á|à|ä|â|ã)", "(A|Á|À|Ä|Â|Ã)",
|
|
6
8
|
"(e|é|è|ë|ê)", "(E|É|È|Ë|Ê)",
|
|
@@ -11,9 +13,10 @@ const accentPatterns = [
|
|
|
11
13
|
const accentInsensitiveFlagTransformer = function (exp) {
|
|
12
14
|
let source = exp.source;
|
|
13
15
|
const flags = exp.flags;
|
|
16
|
+
const nonEscapeBound = (0, resolve_1.resolveRGXToken)((0, constants_1.rgxConstant)("non-escape-bound"));
|
|
14
17
|
accentPatterns.forEach((pattern) => {
|
|
15
18
|
// Replace any of the characters in the pattern with the pattern itself
|
|
16
|
-
source = source.replaceAll(new RegExp(pattern, "g"), pattern);
|
|
19
|
+
source = source.replaceAll(new RegExp(nonEscapeBound + pattern, "g"), pattern);
|
|
17
20
|
});
|
|
18
21
|
return new RegExp(source, flags);
|
|
19
22
|
};
|
package/dist/walker/base.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { RGXPart, RGXCapture } from "./part";
|
|
|
5
5
|
export type RGXWalkerOptions<R> = {
|
|
6
6
|
startingSourcePosition?: number;
|
|
7
7
|
reduced?: R;
|
|
8
|
+
infinite?: boolean;
|
|
9
|
+
looping?: boolean;
|
|
8
10
|
};
|
|
9
11
|
export declare class RGXWalker<R> implements RGXConvertibleToken {
|
|
10
12
|
readonly source: string;
|
|
@@ -14,6 +16,8 @@ export declare class RGXWalker<R> implements RGXConvertibleToken {
|
|
|
14
16
|
reduced: R;
|
|
15
17
|
captures: RGXCapture[];
|
|
16
18
|
namedCaptures: Record<string, RGXCapture[]>;
|
|
19
|
+
infinite: boolean;
|
|
20
|
+
looping: boolean;
|
|
17
21
|
private _stopped;
|
|
18
22
|
static check: (value: unknown) => value is RGXWalker<unknown>;
|
|
19
23
|
static assert: (value: unknown) => asserts value is RGXWalker<unknown>;
|
package/dist/walker/base.js
CHANGED
|
@@ -35,6 +35,8 @@ class RGXWalker {
|
|
|
35
35
|
this.tokens = new collection_1.RGXTokenCollection(tokens, "concat");
|
|
36
36
|
this.tokenPosition = 0;
|
|
37
37
|
this.reduced = options.reduced ?? null;
|
|
38
|
+
this.infinite = options.infinite ?? false;
|
|
39
|
+
this.looping = options.looping ?? false;
|
|
38
40
|
}
|
|
39
41
|
stop() {
|
|
40
42
|
this._stopped = true;
|
|
@@ -73,8 +75,15 @@ class RGXWalker {
|
|
|
73
75
|
return match;
|
|
74
76
|
}
|
|
75
77
|
step() {
|
|
76
|
-
if (this.atTokenEnd())
|
|
78
|
+
if (!this.infinite && !this.looping && this.atTokenEnd()) {
|
|
79
|
+
this._stopped = true;
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
// If we're infinite, we need to manually stop when all is exhausted.
|
|
83
|
+
if ((this.infinite || this.looping) && this.atSourceEnd()) {
|
|
84
|
+
this._stopped = true;
|
|
77
85
|
return null;
|
|
86
|
+
}
|
|
78
87
|
const token = this.currentToken();
|
|
79
88
|
const isPart = token instanceof part_1.RGXPart;
|
|
80
89
|
let silent = false;
|
|
@@ -116,7 +125,12 @@ class RGXWalker {
|
|
|
116
125
|
if (isPart) {
|
|
117
126
|
token.afterCapture?.(captureResult, token, this);
|
|
118
127
|
}
|
|
119
|
-
this.tokenPosition
|
|
128
|
+
if (!this.infinite || this.tokenPosition < this.tokens.length - 1) {
|
|
129
|
+
this.tokenPosition++;
|
|
130
|
+
if (this.looping && this.atTokenEnd()) {
|
|
131
|
+
this.tokenPosition = 0;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
120
134
|
return captureResult;
|
|
121
135
|
}
|
|
122
136
|
stepToToken(predicate) {
|
|
@@ -153,7 +167,9 @@ class RGXWalker {
|
|
|
153
167
|
return this;
|
|
154
168
|
const clone = new RGXWalker(this.source, this.tokens.clone((0, immutability_utils_1.depthDecrement)(1)), {
|
|
155
169
|
startingSourcePosition: this.sourcePosition,
|
|
156
|
-
reduced: (0, immutability_utils_1.extClone)(this.reduced, (0, immutability_utils_1.depthDecrement)(1))
|
|
170
|
+
reduced: (0, immutability_utils_1.extClone)(this.reduced, (0, immutability_utils_1.depthDecrement)(1)),
|
|
171
|
+
infinite: this.infinite,
|
|
172
|
+
looping: this.looping
|
|
157
173
|
});
|
|
158
174
|
clone._tokenPosition = this.tokenPosition;
|
|
159
175
|
clone.captures = (0, immutability_utils_1.extClone)(this.captures, (0, immutability_utils_1.depthDecrement)(1));
|