@ptolemy2002/rgx 7.1.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 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 stopped state.
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:
@@ -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
  }
@@ -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>;
@@ -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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptolemy2002/rgx",
3
- "version": "7.1.0",
3
+ "version": "7.2.0",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",