@ptolemy2002/rgx 5.0.0 → 5.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 +58 -14
- package/dist/class/base.d.ts +4 -3
- package/dist/class/base.js +7 -4
- package/dist/class/index.d.ts +1 -0
- package/dist/class/index.js +1 -0
- package/dist/class/init.js +2 -2
- package/dist/class/repeat.d.ts +3 -2
- package/dist/class/repeat.js +24 -16
- package/dist/class/subpattern.d.ts +13 -0
- package/dist/class/subpattern.js +43 -0
- package/dist/class/wrapper.js +2 -2
- package/dist/concat.js +4 -1
- package/dist/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/errors/insertionRejected.d.ts +6 -0
- package/dist/errors/insertionRejected.js +21 -0
- package/dist/index.js +1 -0
- package/dist/internal/assureAcceptance.d.ts +2 -0
- package/dist/internal/assureAcceptance.js +17 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +1 -0
- package/dist/typeGuards.js +10 -0
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,12 +12,18 @@ import { CloneDepth } from "@ptolemy2002/immutability-utils";
|
|
|
12
12
|
type RGXNoOpToken = null | undefined;
|
|
13
13
|
type RGXLiteralToken = RegExp;
|
|
14
14
|
type RGXNativeToken = string | number | boolean | RGXNoOpToken;
|
|
15
|
-
type RGXConvertibleToken = {
|
|
15
|
+
type RGXConvertibleToken = {
|
|
16
|
+
toRgx: () => RGXToken,
|
|
17
|
+
rgxAcceptInsertion?: (tokens: RGXToken[], flags: ValidRegexFlags) => string | boolean,
|
|
18
|
+
readonly rgxGroupWrap?: boolean,
|
|
19
|
+
readonly rgxIsGroup?: boolean,
|
|
20
|
+
readonly rgxIsRepeatable?: boolean
|
|
21
|
+
};
|
|
16
22
|
type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken | RGXToken[];
|
|
17
23
|
|
|
18
24
|
type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
|
|
19
25
|
type RGXGroupedToken = RGXToken[] | RGXLiteralToken | RGXGroupedConvertibleToken;
|
|
20
|
-
type RGXGroupedConvertibleToken = (RGXConvertibleToken & { readonly rgxIsGroup: true }) | (Omit<RGXConvertibleToken, "
|
|
26
|
+
type RGXGroupedConvertibleToken = (RGXConvertibleToken & { readonly rgxIsGroup: true }) | (Omit<RGXConvertibleToken, "toRgx"> & { toRgx: () => RGXGroupedToken, readonly rgxGroupWrap: true });
|
|
21
27
|
|
|
22
28
|
const validRegexSymbol = Symbol('rgx.ValidRegex');
|
|
23
29
|
type ValidRegexBrandSymbol = typeof validRegexSymbol;
|
|
@@ -48,7 +54,7 @@ type RGXTokenFromType<T extends RGXTokenTypeGuardInput> =
|
|
|
48
54
|
// ... see source for full definition
|
|
49
55
|
;
|
|
50
56
|
|
|
51
|
-
type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT';
|
|
57
|
+
type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'INSERTION_REJECTED';
|
|
52
58
|
|
|
53
59
|
type RangeObject = {
|
|
54
60
|
min?: number | null;
|
|
@@ -212,6 +218,19 @@ constructor(message: string, got: string)
|
|
|
212
218
|
#### Properties
|
|
213
219
|
- `got` (`string`): The conflicting key string.
|
|
214
220
|
|
|
221
|
+
### RGXInsertionRejectedError extends RGXError
|
|
222
|
+
A specific error class for token insertion rejection. This error is thrown when a convertible token's `rgxAcceptInsertion` method returns `false` or a string (rejection reason) during pattern construction via `rgx`, `rgxa`, or `rgxConcat`. The error code is set to `INSERTION_REJECTED` on instantiation.
|
|
223
|
+
|
|
224
|
+
#### Constructor
|
|
225
|
+
```typescript
|
|
226
|
+
constructor(reason?: string | null, message?: string | null)
|
|
227
|
+
```
|
|
228
|
+
- `reason` (`string | null`, optional): The reason the insertion was rejected. Defaults to `null`.
|
|
229
|
+
- `message` (`string | null`, optional): An optional additional message providing more context. Defaults to `null`.
|
|
230
|
+
|
|
231
|
+
#### Properties
|
|
232
|
+
- `reason` (`string | null`): The reason the insertion was rejected, or `null` if no reason was provided.
|
|
233
|
+
|
|
215
234
|
### RGXOutOfBoundsError extends RGXError
|
|
216
235
|
A specific error class for out-of-bounds values. This error is thrown when a numeric value falls outside an expected range. The error code is set to `OUT_OF_BOUNDS` on instantiation.
|
|
217
236
|
|
|
@@ -284,10 +303,11 @@ An abstract base class for creating custom RGX token classes. Subclasses must im
|
|
|
284
303
|
- `rgxGroupWrap` (`boolean`): Returns `true` by default. Controls whether the resolver wraps this token's resolved output in a non-capturing group. Subclasses can override this to prevent double-wrapping (e.g., when the token already wraps itself in a group).
|
|
285
304
|
|
|
286
305
|
#### Methods
|
|
306
|
+
- `rgxAcceptInsertion(tokens: RGXToken[], flags: ValidRegexFlags) => string | boolean`: Called during pattern construction (via `rgx`, `rgxa`, or `rgxConcat`) to allow the token to reject its own insertion based on the surrounding tokens and the pattern's flags. Returns `true` to accept insertion (the default), `false` to reject with no reason, or a string to reject with a reason message. When a token rejects insertion, an `RGXInsertionRejectedError` is thrown. Subclasses can override this to enforce constraints such as requiring certain flags to be present.
|
|
287
307
|
- `or(...others: RGXTokenCollectionInput[]) => RGXClassUnionToken`: Creates an `RGXClassUnionToken` that represents a union (alternation) of this token with the provided others. If any of the `others` are `RGXClassUnionToken` instances, their tokens are flattened into the union rather than nested. If `this` is already an `RGXClassUnionToken`, its existing tokens are preserved and the others are appended.
|
|
288
308
|
- `group(args?: RGXGroupTokenArgs) => RGXGroupToken`: Wraps this token in an `RGXGroupToken` with the provided arguments. The `args` parameter defaults to `{}`, which creates a capturing group with no name. This is a convenience method that creates a new `RGXGroupToken` with `this` as the sole token.
|
|
289
|
-
- `repeat(min?: number, max?: number | null) => RGXRepeatToken`: Wraps this token in an `RGXRepeatToken` with the given repetition bounds. `min` defaults to `1`, `max` defaults to `min`. Pass `null` for `max` to allow unlimited repetitions. This is a convenience method that creates a new `RGXRepeatToken` with `this` as the token. Throws `RGXNotSupportedError` if called on a token with `rgxIsRepeatable` set to `false` (e.g., `RGXLookaroundToken`).
|
|
290
|
-
- `optional() => RGXRepeatToken`: Shorthand for `repeat(0, 1)`. Wraps this token in an `RGXRepeatToken` that matches the token zero or one times. Throws `RGXNotSupportedError` if called on a token with `rgxIsRepeatable` set to `false` (e.g., `RGXLookaroundToken`).
|
|
309
|
+
- `repeat(min?: number, max?: number | null, lazy?: boolean) => RGXRepeatToken`: Wraps this token in an `RGXRepeatToken` with the given repetition bounds. `min` defaults to `1`, `max` defaults to `min`, `lazy` defaults to `false`. Pass `null` for `max` to allow unlimited repetitions. When `lazy` is `true`, the resulting quantifier will be non-greedy. This is a convenience method that creates a new `RGXRepeatToken` with `this` as the token. Throws `RGXNotSupportedError` if called on a token with `rgxIsRepeatable` set to `false` (e.g., `RGXLookaroundToken`).
|
|
310
|
+
- `optional(lazy?: boolean) => RGXRepeatToken`: Shorthand for `repeat(0, 1, lazy)`. Wraps this token in an `RGXRepeatToken` that matches the token zero or one times. `lazy` defaults to `false`. Throws `RGXNotSupportedError` if called on a token with `rgxIsRepeatable` set to `false` (e.g., `RGXLookaroundToken`).
|
|
291
311
|
- `asLookahead(positive?: boolean) => RGXLookaheadToken`: Wraps this token in an `RGXLookaheadToken`. `positive` defaults to `true`. If this token is already an `RGXLookaheadToken`, it is returned as-is without re-wrapping.
|
|
292
312
|
- `asLookbehind(positive?: boolean) => RGXLookbehindToken`: Wraps this token in an `RGXLookbehindToken`. `positive` defaults to `true`. If this token is already an `RGXLookbehindToken`, it is returned as-is without re-wrapping.
|
|
293
313
|
- `resolve() => ValidRegexString`: A convenience method that resolves this token by calling `resolveRGXToken(this)`, returning the resolved regex string representation. Since this method is defined on `RGXClassToken`, it is available on all subclasses including `RGXClassUnionToken`, `RGXGroupToken`, `RGXRepeatToken`, and `RGXLookaroundToken`.
|
|
@@ -354,17 +374,19 @@ A function `rgxRepeat` is provided with the same parameters as this class' const
|
|
|
354
374
|
|
|
355
375
|
#### Constructor
|
|
356
376
|
```typescript
|
|
357
|
-
constructor(token: RGXToken, min?: number, max?: number | null)
|
|
377
|
+
constructor(token: RGXToken, min?: number, max?: number | null, lazy?: boolean)
|
|
358
378
|
```
|
|
359
379
|
- `token` (`RGXToken`): The token to repeat. If the token is not already a grouped token, it will be automatically wrapped in a non-capturing `RGXGroupToken`.
|
|
360
380
|
- `min` (`number`, optional): The minimum number of repetitions. Must be >= 0 and <= `max` (when `max` is not `null`). Non-integer values are floored. Defaults to `1`.
|
|
361
381
|
- `max` (`number | null`, optional): The maximum number of repetitions. Must be >= `min` when not `null`. Non-integer values are floored. Pass `null` for unlimited repetitions. Defaults to `min`.
|
|
382
|
+
- `lazy` (`boolean`, optional): Whether the quantifier should be non-greedy (lazy). Defaults to `false`.
|
|
362
383
|
|
|
363
384
|
#### Properties
|
|
364
385
|
- `token` (`RGXGroupedToken`): The token being repeated. Setting this will throw `RGXNotSupportedError` if the value is a convertible token with `rgxIsRepeatable` set to `false`, and will automatically wrap non-grouped tokens in a non-capturing `RGXGroupToken`.
|
|
365
386
|
- `min` (`number`): The minimum number of repetitions. Setting this validates that the value is >= 0 and <= `max` (when `max` is not `null`), and floors non-integer values. Throws `RGXOutOfBoundsError` if validation fails.
|
|
366
387
|
- `max` (`number | null`): The maximum number of repetitions. Setting this validates that the value is >= `min` when not `null`, and floors non-integer values. Pass `null` for unlimited. Throws `RGXOutOfBoundsError` if validation fails.
|
|
367
|
-
- `
|
|
388
|
+
- `lazy` (`boolean`): Whether the quantifier is non-greedy (lazy). When `true`, a `?` is appended to the `repeaterSuffix` (except when the suffix is `?` or empty, since those cases don't benefit from a lazy modifier). Defaults to `false`.
|
|
389
|
+
- `repeaterSuffix` (`string`): Returns the regex quantifier suffix based on the current `min`, `max`, and `lazy` values: `*` for `{0,}`, `+` for `{1,}`, `?` for `{0,1}`, `{n}` for exact repetitions, `{n,}` for minimum-only, `{n,m}` for a range, or an empty string for `{1,1}` (exactly once, no quantifier needed). When `lazy` is `true`, a `?` is appended to the suffix (e.g., `*?`, `+?`, `{2,5}?`), except when the suffix is already `?` or empty.
|
|
368
390
|
- `rgxGroupWrap` (`false`): Returns `false` as a constant, since the quantifier suffix binds tightly to the preceding group and does not need additional wrapping.
|
|
369
391
|
|
|
370
392
|
#### Methods
|
|
@@ -424,6 +446,28 @@ A function `rgxLookbehind` is provided with the same parameters as this class' c
|
|
|
424
446
|
- `reverse() => RGXLookaheadToken`: Returns a new `RGXLookaheadToken` with the same tokens and positivity.
|
|
425
447
|
- `toRgx() => RegExp`: Resolves the lookbehind to a `RegExp`. Positive lookbehinds produce `(?<=...)` and negative lookbehinds produce `(?<!...)`.
|
|
426
448
|
|
|
449
|
+
### RGXSubpatternToken extends RGXClassToken
|
|
450
|
+
A class representing a backreference to a previously captured group, either by name or by group number. Named backreferences produce `\k<name>` and numbered backreferences produce `\N` (where N is the group number). This is useful for matching the same text that was captured by a previous group.
|
|
451
|
+
|
|
452
|
+
A function `rgxSubpattern` is provided with the same parameters as this class' constructor, for easier instantiation without needing to use the `new` keyword.
|
|
453
|
+
|
|
454
|
+
#### Static Properties
|
|
455
|
+
- `check(value: unknown): value is RGXSubpatternToken`: A type guard that checks if the given value is an instance of `RGXSubpatternToken`.
|
|
456
|
+
- `assert(value: unknown): asserts value is RGXSubpatternToken`: An assertion that checks if the given value is an instance of `RGXSubpatternToken`. If the assertion fails, an `RGXInvalidTokenError` will be thrown.
|
|
457
|
+
|
|
458
|
+
#### Constructor
|
|
459
|
+
```typescript
|
|
460
|
+
constructor(pattern: string | number)
|
|
461
|
+
```
|
|
462
|
+
- `pattern` (`string | number`): The backreference pattern. If a string, it must be a valid identifier (validated via `assertValidIdentifier`) and produces a named backreference (`\k<name>`). If a number, it must be a positive integer (>= 1, as groups are 1-indexed) and produces a numbered backreference (`\N`). Non-integer numbers are floored.
|
|
463
|
+
|
|
464
|
+
#### Properties
|
|
465
|
+
- `pattern` (`string | number`): The backreference pattern. Setting this validates the value: strings must be valid identifiers, numbers must be positive integers (>= 1). Non-integer numbers are floored.
|
|
466
|
+
|
|
467
|
+
#### Methods
|
|
468
|
+
- `toRgx() => RegExp`: Resolves the backreference to a `RegExp`. Named patterns produce `/\k<name>/` and numbered patterns produce `/\N/`.
|
|
469
|
+
- `clone(depth: CloneDepth = "max") => RGXSubpatternToken`: Creates a clone of this token. When `depth` is `0`, returns `this`; otherwise, returns a new `RGXSubpatternToken` with the same pattern.
|
|
470
|
+
|
|
427
471
|
### RGXClassWrapperToken extends RGXClassToken
|
|
428
472
|
A class that wraps any `RGXToken` as an `RGXClassToken`, giving you access to the extended API class tokens provide. It delegates `rgxIsGroup` and `rgxIsRepeatable` to the wrapped token where possible.
|
|
429
473
|
|
|
@@ -442,7 +486,7 @@ constructor(token: RGXToken)
|
|
|
442
486
|
#### Properties
|
|
443
487
|
- `token` (`RGXToken`): The wrapped token.
|
|
444
488
|
- `rgxIsGroup` (`boolean`): Delegates to the wrapped token's group status via `isRGXGroupedToken`. Returns `true` if the wrapped token is a grouped token, otherwise `false`.
|
|
445
|
-
- `rgxIsRepeatable` (`boolean`): If the wrapped token is an `
|
|
489
|
+
- `rgxIsRepeatable` (`boolean`): If the wrapped token is an `RGXConvertibleToken`, delegates to its `rgxIsRepeatable` property (defaulting to `true` if not present). Otherwise, returns `true`.
|
|
446
490
|
|
|
447
491
|
#### Methods
|
|
448
492
|
- `unwrap() => RGXToken`: Returns the original wrapped token.
|
|
@@ -552,11 +596,11 @@ Asserts that the given value is a native token (string, number, boolean, or no-o
|
|
|
552
596
|
function isRGXConvertibleToken(value: unknown, returnCheck?: boolean): value is RGXConvertibleToken
|
|
553
597
|
```
|
|
554
598
|
|
|
555
|
-
Checks if the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap`, `rgxIsRepeatable`, or `rgxIsGroup` properties are present, they must be booleans; otherwise, the check fails.
|
|
599
|
+
Checks if the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap`, `rgxIsRepeatable`, or `rgxIsGroup` properties are present, they must be booleans; otherwise, the check fails. If the `rgxAcceptInsertion` property is present, it must be a callable that returns a `string` or `boolean`; otherwise, the check fails. Validates that `toRgx` is callable and returns a valid `RGXToken` (which can be any RGX token type, including other convertible tokens, allowing for recursive structures). When `returnCheck` is `false`, only checks for the presence and callability of function properties instead of also checking their return values.
|
|
556
600
|
|
|
557
601
|
#### Parameters
|
|
558
602
|
- `value` (`unknown`): The value to check.
|
|
559
|
-
- `returnCheck` (`boolean`, optional): Whether to validate the return value of the `toRgx` method. Defaults to `true`. When `false`, only checks that `toRgx` exists and is callable. **Note**: Setting this to `false` makes the type guard assertion strictly unsafe, as it doesn't verify that the
|
|
603
|
+
- `returnCheck` (`boolean`, optional): Whether to validate the return value of the `toRgx` method. Defaults to `true`. When `false`, only checks that `toRgx` exists and is callable. **Note**: Setting this to `false` makes the type guard assertion strictly unsafe, as it doesn't verify that the methods actually return valid values. However, depending on the type of the value you're checking, you might not need that safety (e.g., when checking values that you know are valid based on other context).
|
|
560
604
|
|
|
561
605
|
#### Returns
|
|
562
606
|
- `boolean`: `true` if the value is a convertible token, otherwise `false`.
|
|
@@ -565,7 +609,7 @@ Checks if the given value is a convertible token (an object with a `toRgx` metho
|
|
|
565
609
|
```typescript
|
|
566
610
|
function assertRGXConvertibleToken(value: unknown, returnCheck?: boolean): asserts value is RGXConvertibleToken
|
|
567
611
|
```
|
|
568
|
-
Asserts that the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap`, `rgxIsRepeatable`, or `rgxIsGroup` properties are present, they must be booleans; otherwise, the assertion fails. When `returnCheck` is `true` (the default), also validates that `toRgx` is callable and returns a valid `RGXToken` (which can be any RGX token type, including other convertible tokens, allowing for recursive structures). If the assertion fails, an `RGXInvalidTokenError` will be thrown.
|
|
612
|
+
Asserts that the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap`, `rgxIsRepeatable`, or `rgxIsGroup` properties are present, they must be booleans; otherwise, the assertion fails. If the `rgxAcceptInsertion` property is present, it must be a callable that returns a `string` or `boolean`; otherwise, the assertion fails. When `returnCheck` is `true` (the default), also validates that `toRgx` is callable and returns a valid `RGXToken` (which can be any RGX token type, including other convertible tokens, allowing for recursive structures). If the assertion fails, an `RGXInvalidTokenError` will be thrown.
|
|
569
613
|
|
|
570
614
|
#### Parameters
|
|
571
615
|
- `value` (`unknown`): The value to assert.
|
|
@@ -868,7 +912,7 @@ For convertible tokens, if the token has an `rgxGroupWrap` property, that value
|
|
|
868
912
|
function rgxConcat(tokens: RGXToken[], groupWrap?: boolean, currentFlags?: string): ValidRegexString
|
|
869
913
|
```
|
|
870
914
|
|
|
871
|
-
A helper function that resolves an array of RGX tokens and concatenates their resolved string representations together. This is useful for cases where you want to concatenate multiple tokens without creating a union between them.
|
|
915
|
+
A helper function that resolves an array of RGX tokens and concatenates their resolved string representations together. This is useful for cases where you want to concatenate multiple tokens without creating a union between them. Before returning, any convertible token in the array that defines `rgxAcceptInsertion` is checked; if it returns `false` or a string, an `RGXInsertionRejectedError` is thrown.
|
|
872
916
|
|
|
873
917
|
#### Parameters
|
|
874
918
|
- `tokens` (`RGXToken[]`): The array of RGX tokens to resolve and concatenate.
|
|
@@ -883,7 +927,7 @@ A helper function that resolves an array of RGX tokens and concatenates their re
|
|
|
883
927
|
function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: RGXToken[]) => ExtRegExp
|
|
884
928
|
```
|
|
885
929
|
|
|
886
|
-
Creates and returns a template tag function that constructs an `ExtRegExp` object from the provided template literal with the provided flags. The template literal can contain RGX tokens, which will be resolved and concatenated with the literal parts to form the final regex pattern.
|
|
930
|
+
Creates and returns a template tag function that constructs an `ExtRegExp` object from the provided template literal with the provided flags. The template literal can contain RGX tokens, which will be resolved and concatenated with the literal parts to form the final regex pattern. Before constructing the pattern, any convertible token that defines `rgxAcceptInsertion` is checked; if it returns `false` or a string, an `RGXInsertionRejectedError` is thrown.
|
|
887
931
|
|
|
888
932
|
The provided `flags` are passed as `currentFlags` to the resolver, enabling inline modifier groups for any `RegExp` literal tokens whose localizable flags (`i`, `m`, `s`) differ from the parent flags. For example, embedding `/foo/i` in a no-flag context produces `(?i:foo)`, while embedding `/bar/` in an `i`-flag context produces `(?-i:bar)`.
|
|
889
933
|
|
|
@@ -918,7 +962,7 @@ const pattern4 = rgx()`${beginning}${caseInsensitiveWord} world${end}`; // /^(?i
|
|
|
918
962
|
```typescript
|
|
919
963
|
function rgxa(tokens: RGXToken[], flags?: string): ExtRegExp
|
|
920
964
|
```
|
|
921
|
-
As an alternative to using the `rgx` template tag, you can directly call `rgxa` with an array of RGX tokens and optional flags to get an `ExtRegExp` object. This is useful in cases where you don't want to use a template literal. Like `rgx`, the provided `flags` are passed as `currentFlags` to the resolver, enabling inline modifier groups for `RegExp` literal tokens whose localizable flags differ.
|
|
965
|
+
As an alternative to using the `rgx` template tag, you can directly call `rgxa` with an array of RGX tokens and optional flags to get an `ExtRegExp` object. This is useful in cases where you don't want to use a template literal. Like `rgx`, the provided `flags` are passed as `currentFlags` to the resolver, enabling inline modifier groups for `RegExp` literal tokens whose localizable flags differ. Before constructing the pattern, any convertible token in the array that defines `rgxAcceptInsertion` is checked; if it returns `false` or a string, an `RGXInsertionRejectedError` is thrown.
|
|
922
966
|
|
|
923
967
|
#### Parameters
|
|
924
968
|
- `tokens` (`RGXToken[]`): The RGX tokens to be resolved and concatenated to form the regex pattern.
|
package/dist/class/base.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RGXConvertibleToken, RGXToken, ValidRegexString } from "../types";
|
|
1
|
+
import { RGXConvertibleToken, RGXToken, ValidRegexFlags, ValidRegexString } from "../types";
|
|
2
2
|
import { RGXTokenCollectionInput } from "../collection";
|
|
3
3
|
import { CloneDepth } from "@ptolemy2002/immutability-utils";
|
|
4
4
|
import type { RGXClassUnionToken } from "./union";
|
|
@@ -9,6 +9,7 @@ import type { RGXLookbehindToken } from "./lookbehind";
|
|
|
9
9
|
export declare abstract class RGXClassToken implements RGXConvertibleToken {
|
|
10
10
|
abstract toRgx(): RGXToken;
|
|
11
11
|
abstract clone(depth?: CloneDepth): ThisType<this>;
|
|
12
|
+
rgxAcceptInsertion(tokens: RGXToken[], flags: ValidRegexFlags): string | boolean;
|
|
12
13
|
static check: (value: unknown) => value is RGXClassToken;
|
|
13
14
|
static assert: (value: unknown) => asserts value is RGXClassToken;
|
|
14
15
|
get rgxIsGroup(): boolean;
|
|
@@ -16,8 +17,8 @@ export declare abstract class RGXClassToken implements RGXConvertibleToken {
|
|
|
16
17
|
get rgxGroupWrap(): boolean;
|
|
17
18
|
or(...others: RGXTokenCollectionInput[]): RGXClassUnionToken;
|
|
18
19
|
group(args?: RGXGroupTokenArgs): RGXGroupToken;
|
|
19
|
-
repeat(min?: number, max?: number | null): RGXRepeatToken;
|
|
20
|
-
optional(): RGXRepeatToken;
|
|
20
|
+
repeat(min?: number, max?: number | null, lazy?: boolean): RGXRepeatToken;
|
|
21
|
+
optional(lazy?: boolean): RGXRepeatToken;
|
|
21
22
|
asLookahead(positive?: boolean): RGXLookaheadToken;
|
|
22
23
|
asLookbehind(positive?: boolean): RGXLookbehindToken;
|
|
23
24
|
resolve(): ValidRegexString;
|
package/dist/class/base.js
CHANGED
|
@@ -4,6 +4,9 @@ exports.RGXClassToken = void 0;
|
|
|
4
4
|
const errors_1 = require("../errors");
|
|
5
5
|
const resolve_1 = require("../resolve");
|
|
6
6
|
class RGXClassToken {
|
|
7
|
+
rgxAcceptInsertion(tokens, flags) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
7
10
|
get rgxIsGroup() {
|
|
8
11
|
return false;
|
|
9
12
|
}
|
|
@@ -19,11 +22,11 @@ class RGXClassToken {
|
|
|
19
22
|
group(args = {}) {
|
|
20
23
|
throw new errors_1.RGXNotImplementedError('RGXClassToken.group(args)', 'call rgxClassInit() first.');
|
|
21
24
|
}
|
|
22
|
-
repeat(min = 1, max = min) {
|
|
23
|
-
throw new errors_1.RGXNotImplementedError('RGXClassToken.repeat(min, max)', 'call rgxClassInit() first.');
|
|
25
|
+
repeat(min = 1, max = min, lazy = false) {
|
|
26
|
+
throw new errors_1.RGXNotImplementedError('RGXClassToken.repeat(min, max, lazy)', 'call rgxClassInit() first.');
|
|
24
27
|
}
|
|
25
|
-
optional() {
|
|
26
|
-
return this.repeat(0, 1);
|
|
28
|
+
optional(lazy = false) {
|
|
29
|
+
return this.repeat(0, 1, lazy);
|
|
27
30
|
}
|
|
28
31
|
asLookahead(positive = true) {
|
|
29
32
|
throw new errors_1.RGXNotImplementedError('RGXClassToken.asLookahead(positive)', 'call rgxClassInit() first.');
|
package/dist/class/index.d.ts
CHANGED
package/dist/class/index.js
CHANGED
|
@@ -23,4 +23,5 @@ __exportStar(require("./lookaround"), exports);
|
|
|
23
23
|
__exportStar(require("./lookahead"), exports);
|
|
24
24
|
__exportStar(require("./lookbehind"), exports);
|
|
25
25
|
__exportStar(require("./wrapper"), exports);
|
|
26
|
+
__exportStar(require("./subpattern"), exports);
|
|
26
27
|
__exportStar(require("./toRGXClassToken"), exports);
|
package/dist/class/init.js
CHANGED
|
@@ -28,10 +28,10 @@ function rgxClassInit() {
|
|
|
28
28
|
base_1.RGXClassToken.prototype.group = function (args = {}) {
|
|
29
29
|
return new group_1.RGXGroupToken(args, [this]);
|
|
30
30
|
};
|
|
31
|
-
base_1.RGXClassToken.prototype.repeat = function (min = 1, max = min) {
|
|
31
|
+
base_1.RGXClassToken.prototype.repeat = function (min = 1, max = min, lazy = false) {
|
|
32
32
|
if (lookaround_1.RGXLookaroundToken.check(this))
|
|
33
33
|
throw new errors_1.RGXNotSupportedError("RGXLookaroundToken.repeat()", "Lookaround tokens cannot be repeated or made optional.");
|
|
34
|
-
return new repeat_1.RGXRepeatToken(this, min, max);
|
|
34
|
+
return new repeat_1.RGXRepeatToken(this, min, max, lazy);
|
|
35
35
|
};
|
|
36
36
|
base_1.RGXClassToken.prototype.asLookahead = function (positive = true) {
|
|
37
37
|
if (lookahead_1.RGXLookaheadToken.check(this))
|
package/dist/class/repeat.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export declare class RGXRepeatToken extends RGXClassToken {
|
|
|
5
5
|
_token: RGXGroupedToken;
|
|
6
6
|
_min: number;
|
|
7
7
|
_max: number | null;
|
|
8
|
+
lazy: boolean;
|
|
8
9
|
static check: (value: unknown) => value is RGXRepeatToken;
|
|
9
10
|
static assert: (value: unknown) => asserts value is RGXRepeatToken;
|
|
10
11
|
get min(): number;
|
|
@@ -14,9 +15,9 @@ export declare class RGXRepeatToken extends RGXClassToken {
|
|
|
14
15
|
get token(): RGXGroupedToken;
|
|
15
16
|
set token(value: RGXToken);
|
|
16
17
|
get rgxGroupWrap(): false;
|
|
17
|
-
constructor(token: RGXToken, min?: number, max?: number | null);
|
|
18
|
+
constructor(token: RGXToken, min?: number, max?: number | null, lazy?: boolean);
|
|
18
19
|
get repeaterSuffix(): string;
|
|
19
20
|
toRgx(): RGXToken;
|
|
20
21
|
clone(depth?: CloneDepth): RGXRepeatToken;
|
|
21
22
|
}
|
|
22
|
-
export declare const rgxRepeat: (token: RGXToken, min?: number | undefined, max?: number | null | undefined) => RGXRepeatToken;
|
|
23
|
+
export declare const rgxRepeat: (token: RGXToken, min?: number | undefined, max?: number | null | undefined, lazy?: boolean | undefined) => RGXRepeatToken;
|
package/dist/class/repeat.js
CHANGED
|
@@ -52,29 +52,37 @@ class RGXRepeatToken extends base_1.RGXClassToken {
|
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
54
54
|
// By default, repeat a fixed number of times.
|
|
55
|
-
constructor(token, min = 1, max = min) {
|
|
55
|
+
constructor(token, min = 1, max = min, lazy = false) {
|
|
56
56
|
super();
|
|
57
57
|
this._max = null;
|
|
58
|
+
this.lazy = false;
|
|
58
59
|
this.token = token;
|
|
59
60
|
this.min = min;
|
|
60
61
|
this.max = max;
|
|
62
|
+
this.lazy = lazy;
|
|
61
63
|
}
|
|
62
64
|
get repeaterSuffix() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
const result = (() => {
|
|
66
|
+
if (this.min === 0 && this.max === null)
|
|
67
|
+
return '*';
|
|
68
|
+
if (this.min === 1 && this.max === null)
|
|
69
|
+
return '+';
|
|
70
|
+
if (this.min === 0 && this.max === 1)
|
|
71
|
+
return '?';
|
|
72
|
+
if (this.max === null)
|
|
73
|
+
return `{${this.min},}`;
|
|
74
|
+
if (this.min === this.max) {
|
|
75
|
+
// No need for a repeater suffix if we're repeating exactly once.
|
|
76
|
+
if (this.min === 1)
|
|
77
|
+
return '';
|
|
78
|
+
return `{${this.min}}`;
|
|
79
|
+
}
|
|
80
|
+
return `{${this.min},${this.max}}`;
|
|
81
|
+
})();
|
|
82
|
+
if (this.lazy && result.length > 0 && result !== "?")
|
|
83
|
+
return result + '?';
|
|
84
|
+
else
|
|
85
|
+
return result;
|
|
78
86
|
}
|
|
79
87
|
toRgx() {
|
|
80
88
|
// No-op if we're repeating zero times.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RGXClassToken } from "./base";
|
|
2
|
+
import { CloneDepth } from "@ptolemy2002/immutability-utils";
|
|
3
|
+
export declare class RGXSubpatternToken extends RGXClassToken {
|
|
4
|
+
_pattern: string | number;
|
|
5
|
+
get pattern(): string | number;
|
|
6
|
+
set pattern(value: string | number);
|
|
7
|
+
static check: (value: unknown) => value is RGXSubpatternToken;
|
|
8
|
+
static assert: (value: unknown) => asserts value is RGXSubpatternToken;
|
|
9
|
+
constructor(pattern: string | number);
|
|
10
|
+
toRgx(): RegExp;
|
|
11
|
+
clone(depth?: CloneDepth): RGXSubpatternToken;
|
|
12
|
+
}
|
|
13
|
+
export declare const rgxSubpattern: (pattern: string | number) => RGXSubpatternToken;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rgxSubpattern = exports.RGXSubpatternToken = void 0;
|
|
4
|
+
const base_1 = require("./base");
|
|
5
|
+
const typeGuards_1 = require("../typeGuards");
|
|
6
|
+
const errors_1 = require("../errors");
|
|
7
|
+
const internal_1 = require("../internal");
|
|
8
|
+
class RGXSubpatternToken extends base_1.RGXClassToken {
|
|
9
|
+
get pattern() {
|
|
10
|
+
return this._pattern;
|
|
11
|
+
}
|
|
12
|
+
set pattern(value) {
|
|
13
|
+
if (typeof value === "string") {
|
|
14
|
+
(0, typeGuards_1.assertValidIdentifier)(value);
|
|
15
|
+
this._pattern = value;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
(0, errors_1.assertInRange)(value, { min: 1 }, "Subpattern group numbers must be positive integers (groups are 1-indexed).");
|
|
19
|
+
this._pattern = Math.floor(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
constructor(pattern) {
|
|
23
|
+
super();
|
|
24
|
+
this.pattern = pattern;
|
|
25
|
+
}
|
|
26
|
+
toRgx() {
|
|
27
|
+
if (typeof this.pattern === "string") {
|
|
28
|
+
return new RegExp(`\\k<${this.pattern}>`);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return new RegExp(`\\${this.pattern}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
clone(depth = "max") {
|
|
35
|
+
if (depth === 0)
|
|
36
|
+
return this;
|
|
37
|
+
return new RGXSubpatternToken(this.pattern);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.RGXSubpatternToken = RGXSubpatternToken;
|
|
41
|
+
RGXSubpatternToken.check = (0, internal_1.createClassGuardFunction)(RGXSubpatternToken);
|
|
42
|
+
RGXSubpatternToken.assert = (0, internal_1.createAssertClassGuardFunction)(RGXSubpatternToken);
|
|
43
|
+
exports.rgxSubpattern = (0, internal_1.createConstructFunction)(RGXSubpatternToken);
|
package/dist/class/wrapper.js
CHANGED
|
@@ -15,8 +15,8 @@ class RGXClassWrapperToken extends base_1.RGXClassToken {
|
|
|
15
15
|
return (0, typeGuards_1.isRGXGroupedToken)(this.token);
|
|
16
16
|
}
|
|
17
17
|
get rgxIsRepeatable() {
|
|
18
|
-
if ((0, typeGuards_1.isRGXToken)(this.token, '
|
|
19
|
-
return this.token.rgxIsRepeatable;
|
|
18
|
+
if ((0, typeGuards_1.isRGXToken)(this.token, 'convertible'))
|
|
19
|
+
return this.token.rgxIsRepeatable ?? true;
|
|
20
20
|
// Assume any other token is repeatable, since we don't know its implementation.
|
|
21
21
|
return true;
|
|
22
22
|
}
|
package/dist/concat.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.rgxConcat = rgxConcat;
|
|
4
|
+
const internal_1 = require("./internal");
|
|
4
5
|
const resolve_1 = require("./resolve");
|
|
5
6
|
// Wrapper for letting an array of tokens be resolved as a concatenation instead of a union.
|
|
6
7
|
function rgxConcat(tokens, groupWrap = true, currentFlags = '') {
|
|
7
|
-
|
|
8
|
+
const result = tokens.map(t => (0, resolve_1.resolveRGXToken)(t, groupWrap, true, currentFlags)).join('');
|
|
9
|
+
(0, internal_1.assureAcceptance)(tokens, currentFlags);
|
|
10
|
+
return result;
|
|
8
11
|
}
|
package/dist/errors/base.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT';
|
|
1
|
+
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'INSERTION_REJECTED';
|
|
2
2
|
export declare class RGXError extends Error {
|
|
3
3
|
_message: string;
|
|
4
4
|
code: RGXErrorCode;
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -25,3 +25,4 @@ __exportStar(require("./outOfBounds"), exports);
|
|
|
25
25
|
__exportStar(require("./invalidFlagTransformerKey"), exports);
|
|
26
26
|
__exportStar(require("./flagTransformerConflict"), exports);
|
|
27
27
|
__exportStar(require("./notSupported"), exports);
|
|
28
|
+
__exportStar(require("./insertionRejected"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXInsertionRejectedError = void 0;
|
|
4
|
+
const base_1 = require("./base");
|
|
5
|
+
class RGXInsertionRejectedError extends base_1.RGXError {
|
|
6
|
+
constructor(reason = null, message = null) {
|
|
7
|
+
super(message || "", "INSERTION_REJECTED");
|
|
8
|
+
this.reason = null;
|
|
9
|
+
this.reason = reason;
|
|
10
|
+
this.name = "RGXInsertionRejectedError";
|
|
11
|
+
}
|
|
12
|
+
calcMessage(message) {
|
|
13
|
+
let result = `Insertion rejected`;
|
|
14
|
+
if (this.reason)
|
|
15
|
+
result += `; Reason: ${this.reason}`;
|
|
16
|
+
if (message)
|
|
17
|
+
result += `; Additional info: ${message}`;
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.RGXInsertionRejectedError = RGXInsertionRejectedError;
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ __exportStar(require("./clone"), exports);
|
|
|
38
38
|
(0, flag_transformer_1.registerCustomFlagTransformers)();
|
|
39
39
|
function rgxa(tokens, flags = '') {
|
|
40
40
|
(0, ExtRegExp_1.assertValidRegexFlags)(flags);
|
|
41
|
+
(0, internal_1.assureAcceptance)(tokens, flags);
|
|
41
42
|
const pattern = (0, concat_1.rgxConcat)(tokens, true, flags);
|
|
42
43
|
return (0, ExtRegExp_1.extRegExp)(pattern, flags);
|
|
43
44
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assureAcceptance = assureAcceptance;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const typeGuards_1 = require("../typeGuards");
|
|
6
|
+
function assureAcceptance(tokens, flags) {
|
|
7
|
+
for (const token of tokens) {
|
|
8
|
+
if ((0, typeGuards_1.isRGXConvertibleToken)(token) && token.rgxAcceptInsertion) {
|
|
9
|
+
const messageOrAccepted = token.rgxAcceptInsertion(tokens, flags);
|
|
10
|
+
if (messageOrAccepted === true)
|
|
11
|
+
continue;
|
|
12
|
+
if (messageOrAccepted === false)
|
|
13
|
+
throw new errors_1.RGXInsertionRejectedError();
|
|
14
|
+
throw new errors_1.RGXInsertionRejectedError(messageOrAccepted);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/internal/index.d.ts
CHANGED
package/dist/internal/index.js
CHANGED
|
@@ -19,3 +19,4 @@ __exportStar(require("./createClassGuardFunction"), exports);
|
|
|
19
19
|
__exportStar(require("./taggedTemplateToArray"), exports);
|
|
20
20
|
__exportStar(require("./isConstructor"), exports);
|
|
21
21
|
__exportStar(require("./getProxy"), exports);
|
|
22
|
+
__exportStar(require("./assureAcceptance"), exports);
|
package/dist/typeGuards.js
CHANGED
|
@@ -98,6 +98,16 @@ function isRGXConvertibleToken(value, returnCheck = true) {
|
|
|
98
98
|
return false;
|
|
99
99
|
if ('rgxIsGroup' in value && typeof value.rgxIsGroup !== 'boolean')
|
|
100
100
|
return false;
|
|
101
|
+
// If the rgxAcceptInsertion property exists, it must be a function that returns a string or boolean.
|
|
102
|
+
if ('rgxAcceptInsertion' in value) {
|
|
103
|
+
if (!(0, is_callable_1.default)(value.rgxAcceptInsertion))
|
|
104
|
+
return false;
|
|
105
|
+
if (returnCheck) {
|
|
106
|
+
const acceptResult = value.rgxAcceptInsertion([], '');
|
|
107
|
+
if (typeof acceptResult !== 'string' && typeof acceptResult !== 'boolean')
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
101
111
|
if ((0, is_callable_1.default)(value.toRgx)) {
|
|
102
112
|
if (!returnCheck)
|
|
103
113
|
return true;
|
package/dist/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type RGXLiteralToken = RegExp;
|
|
|
7
7
|
export type RGXNativeToken = string | number | boolean | RGXNoOpToken;
|
|
8
8
|
export type RGXConvertibleToken = {
|
|
9
9
|
toRgx: () => RGXToken;
|
|
10
|
+
rgxAcceptInsertion?: (tokens: RGXToken[], flags: ValidRegexFlags) => string | boolean;
|
|
10
11
|
readonly rgxGroupWrap?: boolean;
|
|
11
12
|
readonly rgxIsGroup?: boolean;
|
|
12
13
|
readonly rgxIsRepeatable?: boolean;
|
|
@@ -16,7 +17,7 @@ export type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken
|
|
|
16
17
|
export type RGXGroupedToken = RGXToken[] | RGXLiteralToken | RGXGroupedConvertibleToken;
|
|
17
18
|
export type RGXGroupedConvertibleToken = (RGXConvertibleToken & {
|
|
18
19
|
readonly rgxIsGroup: true;
|
|
19
|
-
}) | (Omit<RGXConvertibleToken, "
|
|
20
|
+
}) | (Omit<RGXConvertibleToken, "toRgx"> & {
|
|
20
21
|
toRgx: () => RGXGroupedToken;
|
|
21
22
|
readonly rgxGroupWrap: true;
|
|
22
23
|
});
|