@ptolemy2002/rgx 7.1.0 → 7.3.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 +14 -5
- package/dist/class/repeat.js +1 -1
- package/dist/constants.js +14 -0
- package/dist/typeGuards.js +13 -0
- package/dist/types.d.ts +5 -2
- package/dist/walker/base.d.ts +4 -0
- package/dist/walker/base.js +19 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@ type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken | RGXToke
|
|
|
24
24
|
type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
|
|
25
25
|
type RGXGroupedToken = RGXToken[] | RGXLiteralToken | RGXGroupedConvertibleToken;
|
|
26
26
|
type RGXGroupedConvertibleToken = (RGXConvertibleToken & { readonly rgxIsGroup: true }) | (Omit<RGXConvertibleToken, "toRgx"> & { toRgx: () => RGXGroupedToken, readonly rgxGroupWrap: true });
|
|
27
|
+
type RGXRepeatableConvertibleToken = RGXConvertibleToken & { readonly rgxIsRepeatable: true | undefined };
|
|
27
28
|
|
|
28
29
|
const validRegexSymbol = Symbol('rgx.ValidRegex');
|
|
29
30
|
type ValidRegexBrandSymbol = typeof validRegexSymbol;
|
|
@@ -45,7 +46,7 @@ type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
|
|
|
45
46
|
|
|
46
47
|
type RGXTokenType = 'no-op' | 'literal' | 'native' | 'convertible' | 'class' | RGXTokenType[];
|
|
47
48
|
type RGXTokenTypeFlat = Exclude<RGXTokenType, RGXTokenType[]> | "array";
|
|
48
|
-
type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof RegExp | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
|
|
49
|
+
type RGXTokenTypeGuardInput = "repeatable" | RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof RegExp | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
|
|
49
50
|
type RGXTokenFromType<T extends RGXTokenTypeGuardInput> =
|
|
50
51
|
// Maps token type strings to their corresponding types, e.g.:
|
|
51
52
|
// 'no-op' -> RGXNoOpToken, 'literal' -> RGXLiteralToken, etc.
|
|
@@ -100,6 +101,8 @@ type RGXPartOptions<R, T=string> = {
|
|
|
100
101
|
type RGXWalkerOptions<R> = {
|
|
101
102
|
startingSourcePosition?: number;
|
|
102
103
|
reduced?: R;
|
|
104
|
+
infinite?: boolean;
|
|
105
|
+
looping?: boolean;
|
|
103
106
|
};
|
|
104
107
|
|
|
105
108
|
type RGXWOptions<R = unknown> = Omit<RGXWalkerOptions<R>, "startingSourcePosition"> & {
|
|
@@ -657,6 +660,8 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
657
660
|
- `options` (`RGXWalkerOptions<R>`, optional): Configuration options. Defaults to `{}`.
|
|
658
661
|
- `startingSourcePosition` (`number`, optional): The starting index in the source string. Defaults to `0`.
|
|
659
662
|
- `reduced` (`R`, optional): The initial value for the `reduced` accumulator. Defaults to `null`.
|
|
663
|
+
- `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`.
|
|
664
|
+
- `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
665
|
|
|
661
666
|
#### Properties
|
|
662
667
|
- `source` (`string`): The source string being walked (readonly).
|
|
@@ -666,6 +671,8 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
666
671
|
- `reduced` (`R`): A user-defined accumulator value, typically updated by `RGXPart` callbacks during walking.
|
|
667
672
|
- `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
673
|
- `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.
|
|
674
|
+
- `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.
|
|
675
|
+
- `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
676
|
- `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
677
|
|
|
671
678
|
#### Methods
|
|
@@ -678,12 +685,12 @@ constructor(source: string, tokens: RGXTokenCollectionInput, options?: RGXWalker
|
|
|
678
685
|
- `currentToken() => RGXToken | null`: Returns the token at the current token position, or `null` if at the end.
|
|
679
686
|
- `remainingSource() => string | null`: Returns the remaining source string from the current position onward, or `null` if the source is fully consumed.
|
|
680
687
|
- `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.
|
|
688
|
+
- `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
689
|
- `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
690
|
- `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.
|
|
691
|
+
- `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
692
|
- `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
|
|
693
|
+
- `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
694
|
|
|
688
695
|
## Functions
|
|
689
696
|
The following functions are exported by the library:
|
|
@@ -905,7 +912,7 @@ Converts an `RGXTokenType` to its flat equivalent `RGXTokenTypeFlat`. If the typ
|
|
|
905
912
|
function rgxTokenTypeGuardInputToFlat(type: RGXTokenTypeGuardInput): RGXTokenTypeFlat | null
|
|
906
913
|
```
|
|
907
914
|
|
|
908
|
-
Converts an `RGXTokenTypeGuardInput` to its flat equivalent. If the type is `null`, it returns `null`; if it is an array, it returns `'array'`; if it is an `RGXClassTokenConstructor` (a constructor for an `RGXClassToken` subclass), it returns `'class'` (making it slightly lossy in that case); otherwise, it returns the type as-is.
|
|
915
|
+
Converts an `RGXTokenTypeGuardInput` to its flat equivalent. If the type is `null`, it returns `null`; if it is an array, it returns `'array'`; if it is a RegEx constructor, it returns `'literal`; if it is the `RGXTokenCollection` constructor, it returns `'convertible'`; if it is an `RGXClassTokenConstructor` (a constructor for an `RGXClassToken` subclass), it returns `'class'` (making it slightly lossy in that case); otherwise, it returns the type as-is.
|
|
909
916
|
|
|
910
917
|
#### Parameters
|
|
911
918
|
- `type` (`RGXTokenTypeGuardInput`): The type guard input to convert.
|
|
@@ -924,6 +931,8 @@ When `type` is a constructor, it performs an `instanceof` check against that spe
|
|
|
924
931
|
|
|
925
932
|
When `type` is an array, it checks that every element of the value array is a valid RGX token matching the corresponding type in the `type` array. If `matchLength` is `true` (the default), it also requires that the value array has the same length as the type array; if `false`, it allows the value array to be longer than the type array, as long as all elements up to the length of the type array match and all elements after that are still valid RGX tokens of any type.
|
|
926
933
|
|
|
934
|
+
When `type` is `"repeatable"`, it passes for any token that is not convertible, then checks if `rgxIsRepeatable` is `true | undefined` for convertible tokens.
|
|
935
|
+
|
|
927
936
|
#### Parameters
|
|
928
937
|
- `value` (`unknown`): The value to check.
|
|
929
938
|
- `type` (`T`, optional): The token type to check against. Can be a token type string, `null` (checks against all token types), an `RGXClassTokenConstructor` (checks via `instanceof`), or an array of these. Defaults to `null`.
|
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") && !
|
|
35
|
+
if ((0, typeGuards_1.isRGXToken)(value, "convertible") && !(0, typeGuards_1.isRGXToken)(value, "repeatable")) {
|
|
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
|
@@ -61,6 +61,13 @@ defineRGXConstant("start", {
|
|
|
61
61
|
return /^/;
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
|
+
defineRGXConstant("line-start", {
|
|
65
|
+
rgxGroupWrap: false,
|
|
66
|
+
rgxIsRepeatable: false,
|
|
67
|
+
toRgx() {
|
|
68
|
+
return /^/m;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
64
71
|
defineRGXConstant("end", {
|
|
65
72
|
rgxGroupWrap: false,
|
|
66
73
|
rgxIsRepeatable: false,
|
|
@@ -68,6 +75,13 @@ defineRGXConstant("end", {
|
|
|
68
75
|
return /$/;
|
|
69
76
|
}
|
|
70
77
|
});
|
|
78
|
+
defineRGXConstant("line-end", {
|
|
79
|
+
rgxGroupWrap: false,
|
|
80
|
+
rgxIsRepeatable: false,
|
|
81
|
+
toRgx() {
|
|
82
|
+
return /$/m;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
71
85
|
defineRGXConstant("word-bound", {
|
|
72
86
|
rgxGroupWrap: false,
|
|
73
87
|
rgxIsRepeatable: false,
|
package/dist/typeGuards.js
CHANGED
|
@@ -65,6 +65,8 @@ const e = __importStar(require("./errors"));
|
|
|
65
65
|
const is_callable_1 = __importDefault(require("is-callable"));
|
|
66
66
|
const internal_1 = require("./internal");
|
|
67
67
|
const class_1 = require("./class");
|
|
68
|
+
const ExtRegExp_1 = require("./ExtRegExp");
|
|
69
|
+
const collection_1 = require("./collection");
|
|
68
70
|
function isRGXNoOpToken(value) {
|
|
69
71
|
return value === null || value === undefined;
|
|
70
72
|
}
|
|
@@ -171,8 +173,14 @@ function rgxTokenTypeGuardInputToFlat(type) {
|
|
|
171
173
|
return null;
|
|
172
174
|
if (Array.isArray(type))
|
|
173
175
|
return 'array';
|
|
176
|
+
if (type === RegExp || type === ExtRegExp_1.ExtRegExp)
|
|
177
|
+
return 'literal';
|
|
178
|
+
if (type === collection_1.RGXTokenCollection)
|
|
179
|
+
return 'convertible';
|
|
174
180
|
if ((0, internal_1.isConstructor)(type))
|
|
175
181
|
return 'class';
|
|
182
|
+
if (type === "repeatable")
|
|
183
|
+
return null;
|
|
176
184
|
return type;
|
|
177
185
|
}
|
|
178
186
|
function isRGXToken(value, type = null, matchLength = true) {
|
|
@@ -192,6 +200,11 @@ function isRGXToken(value, type = null, matchLength = true) {
|
|
|
192
200
|
return true;
|
|
193
201
|
if (typeMatches('convertible') && isRGXConvertibleToken(value))
|
|
194
202
|
return true;
|
|
203
|
+
// Non-covertible tokens are repeatable by default. Convertible tokens are only non-repeatable if they have the rgxIsRepeatable property set to false.
|
|
204
|
+
if (type === 'repeatable' && !isRGXConvertibleToken(value, false))
|
|
205
|
+
return true;
|
|
206
|
+
if (type === 'repeatable' && isRGXConvertibleToken(value))
|
|
207
|
+
return value.rgxIsRepeatable ?? true;
|
|
195
208
|
if (typeMatches('array') && isRGXArrayToken(value))
|
|
196
209
|
return true;
|
|
197
210
|
if (Array.isArray(type) && Array.isArray(value) && (!matchLength || type.length === value.length)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -22,10 +22,13 @@ export type RGXGroupedConvertibleToken = (RGXConvertibleToken & {
|
|
|
22
22
|
toRgx: () => RGXGroupedToken;
|
|
23
23
|
readonly rgxGroupWrap: true;
|
|
24
24
|
});
|
|
25
|
+
export type RGXRepeatableConvertibleToken = RGXConvertibleToken & {
|
|
26
|
+
readonly rgxIsRepeatable: true | undefined;
|
|
27
|
+
};
|
|
25
28
|
export type RGXTokenType = 'no-op' | 'literal' | 'native' | 'convertible' | 'class' | RGXTokenType[];
|
|
26
29
|
export type RGXTokenTypeFlat = Exclude<RGXTokenType, RGXTokenType[]> | "array";
|
|
27
|
-
export type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof RegExp | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
|
|
28
|
-
export type RGXTokenFromType<T extends RGXTokenTypeGuardInput> = T extends null ? RGXToken : T extends 'no-op' ? RGXNoOpToken : T extends 'literal' ? RGXLiteralToken : T extends 'native' ? RGXNativeToken : T extends 'convertible' ? RGXConvertibleToken : T extends 'class' ? RGXClassToken : T extends 'array' ? RGXToken[] : T extends new (...args: unknown[]) => infer R ? R : T extends RGXTokenTypeGuardInput[] ? {
|
|
30
|
+
export type RGXTokenTypeGuardInput = "repeatable" | RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof RegExp | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
|
|
31
|
+
export type RGXTokenFromType<T extends RGXTokenTypeGuardInput> = T extends null ? RGXToken : T extends 'no-op' ? RGXNoOpToken : T extends 'literal' ? RGXLiteralToken : T extends 'native' ? RGXNativeToken : T extends 'convertible' ? RGXConvertibleToken : T extends 'class' ? RGXClassToken : T extends 'array' ? RGXToken[] : T extends 'repeatable' ? Exclude<RGXToken, RGXConvertibleToken> | RGXRepeatableConvertibleToken : T extends new (...args: unknown[]) => infer R ? R : T extends RGXTokenTypeGuardInput[] ? {
|
|
29
32
|
[K in keyof T]: T[K] extends RGXTokenTypeGuardInput ? RGXTokenFromType<T[K]> : never;
|
|
30
33
|
} : never;
|
|
31
34
|
export type RangeObject = {
|
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));
|