@ptolemy2002/rgx 4.0.0 → 4.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 +200 -8
- package/dist/class/base.d.ts +3 -0
- package/dist/class/base.js +6 -0
- package/dist/class/group.d.ts +22 -0
- package/dist/class/group.js +59 -0
- package/dist/class/index.d.ts +1 -0
- package/dist/class/index.js +1 -0
- package/dist/class/init.js +4 -0
- package/dist/collection.d.ts +2 -1
- package/dist/collection.js +3 -0
- package/dist/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +2 -0
- package/dist/errors/invalidIdentifier.d.ts +6 -0
- package/dist/errors/invalidIdentifier.js +15 -0
- package/dist/errors/outOfBounds.d.ts +20 -0
- package/dist/errors/outOfBounds.js +109 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/resolve.d.ts +1 -1
- package/dist/resolve.js +6 -4
- package/dist/typeGuards.d.ts +2 -0
- package/dist/typeGuards.js +14 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.js +2 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/normalizeRegexFlags.d.ts +1 -0
- package/dist/utils/normalizeRegexFlags.js +19 -0
- package/dist/utils/regexMatchAtPosition.d.ts +1 -0
- package/dist/utils/regexMatchAtPosition.js +16 -0
- package/dist/utils/regexWithFlags.d.ts +1 -0
- package/dist/utils/regexWithFlags.js +13 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ import { Branded } from "@ptolemy2002/ts-brand-utils";
|
|
|
8
8
|
type RGXNoOpToken = null | undefined;
|
|
9
9
|
type RGXLiteralToken = RegExp;
|
|
10
10
|
type RGXNativeToken = string | number | boolean | RGXNoOpToken;
|
|
11
|
-
type RGXConvertibleToken = { toRgx: () => RGXToken };
|
|
11
|
+
type RGXConvertibleToken = { toRgx: () => RGXToken, readonly rgxGroupWrap?: boolean };
|
|
12
12
|
type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken | RGXToken[];
|
|
13
13
|
type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
|
|
14
14
|
|
|
@@ -20,6 +20,10 @@ const validVanillaRegexFlagsSymbol = Symbol('rgx.ValidVanillaRegexFlags');
|
|
|
20
20
|
type ValidVanillaRegexFlagsBrandSymbol = typeof validVanillaRegexFlagsSymbol;
|
|
21
21
|
type ValidVanillaRegexFlags = Branded<string, [ValidVanillaRegexFlagsBrandSymbol]>;
|
|
22
22
|
|
|
23
|
+
const validIdentifierSymbol = Symbol('rgx.ValidIdentifier');
|
|
24
|
+
type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
|
|
25
|
+
type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
|
|
26
|
+
|
|
23
27
|
type RGXTokenType = 'no-op' | 'literal' | 'native' | 'convertible' | 'class' | RGXTokenType[];
|
|
24
28
|
type RGXTokenTypeFlat = Exclude<RGXTokenType, RGXTokenType[]> | "array";
|
|
25
29
|
type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | RGXTokenTypeGuardInput[];
|
|
@@ -30,7 +34,14 @@ type RGXTokenFromType<T extends RGXTokenTypeGuardInput> =
|
|
|
30
34
|
// ... see source for full definition
|
|
31
35
|
;
|
|
32
36
|
|
|
33
|
-
type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED';
|
|
37
|
+
type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS';
|
|
38
|
+
|
|
39
|
+
type RangeObject = {
|
|
40
|
+
min?: number | null;
|
|
41
|
+
max?: number | null;
|
|
42
|
+
inclusiveLeft?: boolean;
|
|
43
|
+
inclusiveRight?: boolean;
|
|
44
|
+
};
|
|
34
45
|
type ExpectedTokenType = {
|
|
35
46
|
type: "tokenType";
|
|
36
47
|
values: RGXTokenTypeFlat[];
|
|
@@ -42,6 +53,11 @@ type RGXTokenCollectionMode = 'union' | 'concat';
|
|
|
42
53
|
type RGXTokenCollectionInput = RGXToken | RGXTokenCollection;
|
|
43
54
|
|
|
44
55
|
type RGXUnionInsertionPosition = 'prefix' | 'suffix';
|
|
56
|
+
|
|
57
|
+
type RGXGroupTokenArgs = {
|
|
58
|
+
name?: string | null;
|
|
59
|
+
capturing?: boolean;
|
|
60
|
+
};
|
|
45
61
|
```
|
|
46
62
|
|
|
47
63
|
## Classes
|
|
@@ -117,6 +133,49 @@ constructor(functionality: string, message?: string | null)
|
|
|
117
133
|
#### Methods
|
|
118
134
|
- `toString() => string`: Returns a formatted string indicating the unimplemented functionality and any additional message.
|
|
119
135
|
|
|
136
|
+
### RGXInvalidIdentifierError extends RGXError
|
|
137
|
+
A specific error class for invalid identifiers. This error is thrown when a string fails validation as a valid identifier. The error code is set to `INVALID_IDENTIFIER` on instantiation.
|
|
138
|
+
|
|
139
|
+
#### Constructor
|
|
140
|
+
```typescript
|
|
141
|
+
constructor(message: string, got: string)
|
|
142
|
+
```
|
|
143
|
+
- `message` (`string`): The error message.
|
|
144
|
+
- `got` (`string`): The actual string that was received, which failed validation.
|
|
145
|
+
|
|
146
|
+
#### Properties
|
|
147
|
+
- `got` (`string`): The actual string that was received, which failed validation.
|
|
148
|
+
|
|
149
|
+
#### Methods
|
|
150
|
+
- `toString() => string`: Returns a formatted string indicating the invalid identifier and the reason for failure.
|
|
151
|
+
|
|
152
|
+
### RGXOutOfBoundsError extends RGXError
|
|
153
|
+
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.
|
|
154
|
+
|
|
155
|
+
#### Constructor
|
|
156
|
+
```typescript
|
|
157
|
+
constructor(message: string, got: number, { min, max, inclusiveLeft, inclusiveRight }?: RangeObject)
|
|
158
|
+
```
|
|
159
|
+
- `message` (`string`): The error message.
|
|
160
|
+
- `got` (`number`): The actual numeric value that was received, which fell outside the expected range.
|
|
161
|
+
- `min` (`number | null`, optional): The minimum bound of the range. Defaults to `null` (no minimum).
|
|
162
|
+
- `max` (`number | null`, optional): The maximum bound of the range. Defaults to `null` (no maximum). Setting `min` to a value greater than `max` will adjust `max` to equal `min`, and vice versa.
|
|
163
|
+
- `inclusiveLeft` (`boolean`, optional): Whether the minimum bound is inclusive. Defaults to `true`.
|
|
164
|
+
- `inclusiveRight` (`boolean`, optional): Whether the maximum bound is inclusive. Defaults to `true`.
|
|
165
|
+
|
|
166
|
+
#### Properties
|
|
167
|
+
- `got` (`number`): The actual numeric value that was received.
|
|
168
|
+
- `min` (`number | null`): The minimum bound of the range. Setting this to a value greater than `max` will adjust `max` to equal `min`.
|
|
169
|
+
- `max` (`number | null`): The maximum bound of the range. Setting this to a value less than `min` will adjust `min` to equal `max`.
|
|
170
|
+
- `inclusiveLeft` (`boolean`): Whether the minimum bound is inclusive.
|
|
171
|
+
- `inclusiveRight` (`boolean`): Whether the maximum bound is inclusive.
|
|
172
|
+
|
|
173
|
+
#### Methods
|
|
174
|
+
- `failedAtMin() => boolean`: Returns `true` if the `got` value is below the minimum bound (respecting `inclusiveLeft`), otherwise `false`. Returns `false` if `min` is `null`.
|
|
175
|
+
- `failedAtMax() => boolean`: Returns `true` if the `got` value is above the maximum bound (respecting `inclusiveRight`), otherwise `false`. Returns `false` if `max` is `null`.
|
|
176
|
+
- `failedAtAny() => boolean`: Returns `true` if the value failed at either the minimum or maximum bound.
|
|
177
|
+
- `toString() => string`: Returns a formatted string indicating the out-of-bounds value, the expected range, and which bound was violated.
|
|
178
|
+
|
|
120
179
|
### RGXTokenCollection
|
|
121
180
|
A class representing a collection of RGX tokens. This class manages collections of RGX tokens like an array, but with additional metadata about the collection mode (union or concat). Since `toRgx()` returns a `RegExp`, instances of this class satisfy the `RGXConvertibleToken` interface and can be used directly as tokens in `rgx`, `rgxa`, and other token-accepting functions.
|
|
122
181
|
|
|
@@ -132,6 +191,7 @@ constructor(tokens: RGXTokenCollectionInput = [], mode: RGXTokenCollectionMode =
|
|
|
132
191
|
#### Properties
|
|
133
192
|
- `tokens` (`RGXToken[]`): The array of RGX tokens managed by the collection. In almost all cases, use `getTokens()` instead of accessing this property directly, as it will be copied to prevent external mutation.
|
|
134
193
|
- `mode` (`RGXTokenCollectionMode`): The mode of the collection, either 'union' or 'concat'. This determines how the tokens in the collection will be resolved when `toRgx()` is called.
|
|
194
|
+
- `resolve() => ValidRegexString`: A convenience method that resolves this collection by calling `resolveRGXToken(this)`, returning the resolved regex string representation.
|
|
135
195
|
- `toRgx() => RegExp`: A method that resolves the collection to a `RegExp` object based on the collection mode. In 'union' mode, the tokens are resolved as alternatives (using the `|` operator), while in 'concat' mode, the tokens are resolved as concatenated together. No flags are applied to the resulting `RegExp`. Since this method returns a `RegExp` (which is `RGXLiteralToken`), `RGXTokenCollection` instances satisfy the `RGXConvertibleToken` interface and can be used directly as tokens in `rgx`, `rgxa`, and other token-accepting functions.
|
|
136
196
|
- `getTokens() => RGXToken[]`: A method that returns a copy of the array of RGX tokens managed by the collection. This is used to prevent external mutation of the internal `tokens` array.
|
|
137
197
|
- `toArray() => RGXToken[]`: An alias for `getTokens()`, provided for convenience.
|
|
@@ -157,10 +217,12 @@ An abstract base class for creating custom RGX token classes. Subclasses must im
|
|
|
157
217
|
|
|
158
218
|
#### Properties
|
|
159
219
|
- `isGroup` (`boolean`): Returns `false` by default. Subclasses can override this to indicate whether the token represents a group.
|
|
220
|
+
- `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).
|
|
160
221
|
|
|
161
222
|
#### Methods
|
|
162
223
|
- `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.
|
|
163
|
-
- `
|
|
224
|
+
- `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.
|
|
225
|
+
- `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` and `RGXGroupToken`.
|
|
164
226
|
|
|
165
227
|
### RGXClassUnionToken extends RGXClassToken
|
|
166
228
|
A class representing a union (alternation) of RGX tokens. This is typically created via the `or()` method on `RGXClassToken`, but can also be instantiated directly.
|
|
@@ -187,6 +249,34 @@ constructor(tokens: RGXTokenCollectionInput = [])
|
|
|
187
249
|
- `cleanTokens() => this`: Expands any nested union tokens and removes duplicates from the internal token collection. Returns `this` for chaining. Called automatically during construction and after `add` or `concat`.
|
|
188
250
|
- `toRgx() => RegExp`: Resolves the union by calling `toRgx()` on the internal `RGXTokenCollection`, returning a `RegExp`.
|
|
189
251
|
|
|
252
|
+
### RGXGroupToken extends RGXClassToken
|
|
253
|
+
A class representing a group (capturing, non-capturing, or named) wrapping one or more RGX tokens. This is typically created via the `group()` method on `RGXClassToken`, but can also be instantiated directly.
|
|
254
|
+
|
|
255
|
+
A function `rgxGroup` is provided with the same parameters as this class' constructor, for easier instantiation without needing to use the `new` keyword.
|
|
256
|
+
|
|
257
|
+
#### Static Properties
|
|
258
|
+
- `check(value: unknown): value is RGXGroupToken`: A type guard that checks if the given value is an instance of `RGXGroupToken`.
|
|
259
|
+
- `assert(value: unknown): asserts value is RGXGroupToken`: An assertion that checks if the given value is an instance of `RGXGroupToken`. If the assertion fails, an `RGXInvalidTokenError` will be thrown.
|
|
260
|
+
|
|
261
|
+
#### Constructor
|
|
262
|
+
```typescript
|
|
263
|
+
constructor(args?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput)
|
|
264
|
+
```
|
|
265
|
+
- `args` (`RGXGroupTokenArgs`, optional): An object specifying the group configuration. Defaults to `{}`.
|
|
266
|
+
- `name` (`string | null`, optional): The name of the group for named capture groups. Must be a valid identifier (validated via `assertValidIdentifier`). Defaults to `null`.
|
|
267
|
+
- `capturing` (`boolean`, optional): Whether the group is capturing. Defaults to `true`. Setting this to `false` also clears any `name`.
|
|
268
|
+
- `tokens` (`RGXTokenCollectionInput`, optional): The tokens to be wrapped by the group. Internally stored as an `RGXTokenCollection` in 'concat' mode. Defaults to an empty array.
|
|
269
|
+
|
|
270
|
+
#### Properties
|
|
271
|
+
- `tokens` (`RGXTokenCollection`): The internal collection of tokens managed in 'concat' mode.
|
|
272
|
+
- `name` (`string | null`): The name of the group. Setting this to a non-null value validates it as a valid identifier via `assertValidIdentifier`.
|
|
273
|
+
- `capturing` (`boolean`): Whether the group is capturing. Any named group is automatically capturing (returns `true` when `name` is not `null`). Setting this to `false` also clears `name` to `null`.
|
|
274
|
+
- `isGroup` (`boolean`): Returns `true`, indicating this token represents a group.
|
|
275
|
+
- `rgxGroupWrap` (`boolean`): Returns `false`, since the group already wraps itself, preventing the resolver from double-wrapping.
|
|
276
|
+
|
|
277
|
+
#### Methods
|
|
278
|
+
- `toRgx() => RegExp`: Resolves the group by concatenating the internal tokens and wrapping the result in the appropriate group syntax: `(?<name>...)` for named groups, `(?:...)` for non-capturing groups, or `(...)` for capturing groups.
|
|
279
|
+
|
|
190
280
|
## Functions
|
|
191
281
|
The following functions are exported by the library:
|
|
192
282
|
|
|
@@ -273,7 +363,7 @@ Asserts that the given value is a native token (string, number, boolean, or no-o
|
|
|
273
363
|
function isRGXConvertibleToken(value: unknown, returnCheck?: boolean): value is RGXConvertibleToken
|
|
274
364
|
```
|
|
275
365
|
|
|
276
|
-
Checks if the given value is a convertible token (an object with a `toRgx` method). 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).
|
|
366
|
+
Checks if the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap` property is present, it must be a boolean; otherwise, the check 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).
|
|
277
367
|
|
|
278
368
|
#### Parameters
|
|
279
369
|
- `value` (`unknown`): The value to check.
|
|
@@ -286,7 +376,7 @@ Checks if the given value is a convertible token (an object with a `toRgx` metho
|
|
|
286
376
|
```typescript
|
|
287
377
|
function assertRGXConvertibleToken(value: unknown, returnCheck?: boolean): asserts value is RGXConvertibleToken
|
|
288
378
|
```
|
|
289
|
-
Asserts that the given value is a convertible token (an object with a `toRgx` method). 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.
|
|
379
|
+
Asserts that the given value is a convertible token (an object with a `toRgx` method). If the `rgxGroupWrap` property is present, it must be a 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.
|
|
290
380
|
|
|
291
381
|
#### Parameters
|
|
292
382
|
- `value` (`unknown`): The value to assert.
|
|
@@ -499,6 +589,30 @@ Asserts that the given string is a valid combination of vanilla regex flags (g,
|
|
|
499
589
|
#### Returns
|
|
500
590
|
- `void`: This function does not return a value, but will throw an error if the assertion fails.
|
|
501
591
|
|
|
592
|
+
### isValidIdentifier
|
|
593
|
+
```typescript
|
|
594
|
+
function isValidIdentifier(value: string): value is ValidIdentifier
|
|
595
|
+
```
|
|
596
|
+
Checks if the given string is a valid identifier, used for group names and backreferences. Valid identifiers contain only letters, digits, dollar signs, and underscores, and cannot start with a digit.
|
|
597
|
+
|
|
598
|
+
#### Parameters
|
|
599
|
+
- `value` (`string`): The string to check.
|
|
600
|
+
|
|
601
|
+
#### Returns
|
|
602
|
+
- `boolean`: `true` if the string is a valid identifier, otherwise `false`.
|
|
603
|
+
|
|
604
|
+
### assertValidIdentifier
|
|
605
|
+
```typescript
|
|
606
|
+
function assertValidIdentifier(value: string): asserts value is ValidIdentifier
|
|
607
|
+
```
|
|
608
|
+
Asserts that the given string is a valid identifier, used for group names and backreferences. Valid identifiers contain only letters, digits, dollar signs, and underscores, and cannot start with a digit. If the assertion fails, an `RGXInvalidIdentifierError` will be thrown.
|
|
609
|
+
|
|
610
|
+
#### Parameters
|
|
611
|
+
- `value` (`string`): The string to assert.
|
|
612
|
+
|
|
613
|
+
#### Returns
|
|
614
|
+
- `void`: This function does not return a value, but will throw an error if the assertion fails.
|
|
615
|
+
|
|
502
616
|
### escapeRegex
|
|
503
617
|
```typescript
|
|
504
618
|
function escapeRegex(value: string): ValidRegexString
|
|
@@ -514,14 +628,17 @@ Escapes special regex characters in the given string and brands the result as a
|
|
|
514
628
|
|
|
515
629
|
### resolveRGXToken
|
|
516
630
|
```typescript
|
|
517
|
-
function resolveRGXToken(token: RGXToken, groupWrap?: boolean): ValidRegexString
|
|
631
|
+
function resolveRGXToken(token: RGXToken, groupWrap?: boolean, topLevel?: boolean): ValidRegexString
|
|
518
632
|
```
|
|
519
633
|
|
|
520
634
|
Resolves an RGX token to a string. No-op tokens resolve to an empty string, literal tokens are included as-is (wrapped in a non-capturing group when `groupWrap` is `true`), native tokens are converted to strings and escaped, convertible tokens are converted using their `toRgx` method and then resolved recursively, and arrays of tokens are resolved as unions of their resolved elements (repeats removed, placed in a non-capturing group when `groupWrap` is `true`).
|
|
521
635
|
|
|
636
|
+
For convertible tokens, if the token has an `rgxGroupWrap` property, that value always takes precedence. If `rgxGroupWrap` is not present, the behavior depends on whether the call is top-level: at the top level, the `groupWrap` parameter is passed through; in recursive calls, it falls back to `true` regardless of the `groupWrap` parameter. This ensures that the caller's `groupWrap` preference only affects the outermost convertible token and does not leak into deeply nested resolution.
|
|
637
|
+
|
|
522
638
|
#### Parameters
|
|
523
639
|
- `token` (`RGXToken`): The RGX token to resolve.
|
|
524
|
-
- `groupWrap` (`boolean`, optional): Whether to wrap literal tokens and array unions in non-capturing groups (`(?:...)`). Defaults to `true`. When `false`, literals use their raw source and array unions omit the wrapping group.
|
|
640
|
+
- `groupWrap` (`boolean`, optional): Whether to wrap literal tokens and array unions in non-capturing groups (`(?:...)`). Defaults to `true`. When `false`, literals use their raw source and array unions omit the wrapping group. For convertible tokens, the token's `rgxGroupWrap` property always takes precedence; otherwise, this value is only passed through at the top level (in recursive calls it falls back to `true`). Array union elements always use `groupWrap=true` internally.
|
|
641
|
+
- `topLevel` (`boolean`, optional): Tracks whether the current call is the initial (top-level) invocation. Defaults to `true`. **Warning**: This parameter is intended for internal use by the resolver's own recursion. External callers should not set this parameter, as doing so may produce unexpected wrapping behavior.
|
|
525
642
|
|
|
526
643
|
#### Returns
|
|
527
644
|
- `ValidRegexString`: The resolved string representation of the RGX token. This is guaranteed to be a valid regex string, as convertible tokens are validated to only produce valid regex strings or arrays of valid regex strings.
|
|
@@ -615,7 +732,82 @@ Removes duplicate tokens from the provided list using `Set` equality and returns
|
|
|
615
732
|
function rgxClassInit(): void
|
|
616
733
|
```
|
|
617
734
|
|
|
618
|
-
Initializes internal method patches required for `RGXClassToken` subclass methods (such as `or`) to work correctly. This function is called automatically when importing from the main module entry point, so you typically do not need to call it yourself. It only needs to be called manually if you import directly from sub-modules.
|
|
735
|
+
Initializes internal method patches required for `RGXClassToken` subclass methods (such as `or` and `group`) to work correctly. This function is called automatically when importing from the main module entry point, so you typically do not need to call it yourself. It only needs to be called manually if you import directly from sub-modules.
|
|
736
|
+
|
|
737
|
+
### isInRange
|
|
738
|
+
```typescript
|
|
739
|
+
function isInRange(value: number, { min, max, inclusiveLeft, inclusiveRight }?: RangeObject): boolean
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
Checks if the given numeric value falls within the specified range.
|
|
743
|
+
|
|
744
|
+
#### Parameters
|
|
745
|
+
- `value` (`number`): The value to check.
|
|
746
|
+
- `min` (`number | null`, optional): The minimum bound of the range. Defaults to `null` (no minimum).
|
|
747
|
+
- `max` (`number | null`, optional): The maximum bound of the range. Defaults to `null` (no maximum).
|
|
748
|
+
- `inclusiveLeft` (`boolean`, optional): Whether the minimum bound is inclusive. Defaults to `true`.
|
|
749
|
+
- `inclusiveRight` (`boolean`, optional): Whether the maximum bound is inclusive. Defaults to `true`.
|
|
750
|
+
|
|
751
|
+
#### Returns
|
|
752
|
+
- `boolean`: `true` if the value is within the specified range, otherwise `false`.
|
|
753
|
+
|
|
754
|
+
### assertInRange
|
|
755
|
+
```typescript
|
|
756
|
+
function assertInRange(value: number, range: RangeObject, message?: string): void
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Asserts that the given numeric value falls within the specified range. If the assertion fails, an `RGXOutOfBoundsError` will be thrown.
|
|
760
|
+
|
|
761
|
+
#### Parameters
|
|
762
|
+
- `value` (`number`): The value to assert.
|
|
763
|
+
- `range` (`RangeObject`): The range to check against.
|
|
764
|
+
- `message` (`string`, optional): A custom error message. Defaults to `"Value out of bounds"`.
|
|
765
|
+
|
|
766
|
+
#### Returns
|
|
767
|
+
- `void`: This function does not return a value, but will throw an error if the assertion fails.
|
|
768
|
+
|
|
769
|
+
### normalizeVanillaRegexFlags
|
|
770
|
+
```typescript
|
|
771
|
+
function normalizeVanillaRegexFlags(flags: string): string
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
Normalizes a string of vanilla regex flags by removing duplicate flags while preserving order. If any character in the string is not a valid vanilla regex flag (g, i, m, s, u, y), an `RGXInvalidVanillaRegexFlagsError` will be thrown.
|
|
775
|
+
|
|
776
|
+
#### Parameters
|
|
777
|
+
- `flags` (`string`): The flags string to normalize.
|
|
778
|
+
|
|
779
|
+
#### Returns
|
|
780
|
+
- `string`: The normalized flags string with duplicates removed.
|
|
781
|
+
|
|
782
|
+
### regexWithFlags
|
|
783
|
+
```typescript
|
|
784
|
+
function regexWithFlags(exp: RegExp, flags: string, replace?: boolean): RegExp
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
Creates a new `RegExp` from an existing one with additional or replaced flags. When `replace` is `false` (the default), the provided flags are merged with the existing flags and normalized (duplicates removed). When `replace` is `true`, the existing flags are discarded and only the provided flags are used. The provided flags are validated as valid vanilla regex flags via `assertValidVanillaRegexFlags`.
|
|
788
|
+
|
|
789
|
+
#### Parameters
|
|
790
|
+
- `exp` (`RegExp`): The source regular expression.
|
|
791
|
+
- `flags` (`string`): The flags to add or replace with. Must be valid vanilla regex flags, or an `RGXInvalidVanillaRegexFlagsError` will be thrown.
|
|
792
|
+
- `replace` (`boolean`, optional): Whether to replace the existing flags entirely instead of merging. Defaults to `false`.
|
|
793
|
+
|
|
794
|
+
#### Returns
|
|
795
|
+
- `RegExp`: A new `RegExp` with the same source pattern and the resulting flags.
|
|
796
|
+
|
|
797
|
+
### regexMatchAtPosition
|
|
798
|
+
```typescript
|
|
799
|
+
function regexMatchAtPosition(regex: RegExp, str: string, position: number): boolean
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
Tests whether the given regular expression matches at a specific position in the string. This is done by creating a sticky (`y` flag) copy of the regex and setting its `lastIndex` to the desired position. The position must be within the bounds of the string (>= 0 and < string length), or an `RGXOutOfBoundsError` will be thrown.
|
|
803
|
+
|
|
804
|
+
#### Parameters
|
|
805
|
+
- `regex` (`RegExp`): The regular expression to test.
|
|
806
|
+
- `str` (`string`): The string to test against.
|
|
807
|
+
- `position` (`number`): The zero-based index in the string at which to test the match. Must be >= 0 and < `str.length`.
|
|
808
|
+
|
|
809
|
+
#### Returns
|
|
810
|
+
- `boolean`: `true` if the regex matches at the specified position, otherwise `false`.
|
|
619
811
|
|
|
620
812
|
## Peer Dependencies
|
|
621
813
|
- `@ptolemy2002/immutability-utils` ^2.0.0
|
package/dist/class/base.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { RGXToken, ValidRegexString } from "../types";
|
|
2
2
|
import { RGXTokenCollectionInput } from "../collection";
|
|
3
3
|
import type { RGXClassUnionToken } from "./union";
|
|
4
|
+
import type { RGXGroupToken, RGXGroupTokenArgs } from "./group";
|
|
4
5
|
export declare abstract class RGXClassToken {
|
|
5
6
|
abstract toRgx(): RGXToken;
|
|
6
7
|
static check: (value: unknown) => value is RGXClassToken;
|
|
7
8
|
static assert: (value: unknown) => asserts value is RGXClassToken;
|
|
8
9
|
get isGroup(): boolean;
|
|
10
|
+
get rgxGroupWrap(): boolean;
|
|
9
11
|
or(...others: RGXTokenCollectionInput[]): RGXClassUnionToken;
|
|
12
|
+
group(args?: RGXGroupTokenArgs): RGXGroupToken;
|
|
10
13
|
resolve(): ValidRegexString;
|
|
11
14
|
}
|
package/dist/class/base.js
CHANGED
|
@@ -7,9 +7,15 @@ class RGXClassToken {
|
|
|
7
7
|
get isGroup() {
|
|
8
8
|
return false;
|
|
9
9
|
}
|
|
10
|
+
get rgxGroupWrap() {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
10
13
|
or(...others) {
|
|
11
14
|
throw new errors_1.RGXNotImplementedError('RGXClassToken.or(...others)', 'call rgxClassInit() first.');
|
|
12
15
|
}
|
|
16
|
+
group(args = {}) {
|
|
17
|
+
throw new errors_1.RGXNotImplementedError('RGXClassToken.group(args)', 'call rgxClassInit() first.');
|
|
18
|
+
}
|
|
13
19
|
resolve() {
|
|
14
20
|
return (0, resolve_1.resolveRGXToken)(this);
|
|
15
21
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RGXTokenCollection, RGXTokenCollectionInput } from "../collection";
|
|
2
|
+
import { RGXClassToken } from "./base";
|
|
3
|
+
export type RGXGroupTokenArgs = {
|
|
4
|
+
name?: string | null;
|
|
5
|
+
capturing?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare class RGXGroupToken extends RGXClassToken {
|
|
8
|
+
tokens: RGXTokenCollection;
|
|
9
|
+
_name: string | null;
|
|
10
|
+
_capturing: boolean;
|
|
11
|
+
static check: (value: unknown) => value is RGXGroupToken;
|
|
12
|
+
static assert: (value: unknown) => asserts value is RGXGroupToken;
|
|
13
|
+
get name(): string | null;
|
|
14
|
+
set name(value: string | null);
|
|
15
|
+
get capturing(): boolean;
|
|
16
|
+
set capturing(value: boolean);
|
|
17
|
+
get isGroup(): boolean;
|
|
18
|
+
get rgxGroupWrap(): boolean;
|
|
19
|
+
constructor({ name, capturing }?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput);
|
|
20
|
+
toRgx(): RegExp;
|
|
21
|
+
}
|
|
22
|
+
export declare const rgxGroup: (args_0?: RGXGroupTokenArgs | undefined, tokens?: RGXTokenCollectionInput) => RGXGroupToken;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rgxGroup = exports.RGXGroupToken = void 0;
|
|
4
|
+
const collection_1 = require("../collection");
|
|
5
|
+
const base_1 = require("./base");
|
|
6
|
+
const internal_1 = require("../internal");
|
|
7
|
+
const typeGuards_1 = require("../typeGuards");
|
|
8
|
+
class RGXGroupToken extends base_1.RGXClassToken {
|
|
9
|
+
get name() {
|
|
10
|
+
return this._name;
|
|
11
|
+
}
|
|
12
|
+
set name(value) {
|
|
13
|
+
if (value !== null)
|
|
14
|
+
(0, typeGuards_1.assertValidIdentifier)(value);
|
|
15
|
+
this._name = value;
|
|
16
|
+
}
|
|
17
|
+
get capturing() {
|
|
18
|
+
// Any named group is automatically capturing
|
|
19
|
+
return this.name !== null || this._capturing;
|
|
20
|
+
}
|
|
21
|
+
set capturing(value) {
|
|
22
|
+
if (!value)
|
|
23
|
+
this.name = null; // Non-capturing groups cannot have names
|
|
24
|
+
this._capturing = value;
|
|
25
|
+
}
|
|
26
|
+
get isGroup() {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
get rgxGroupWrap() {
|
|
30
|
+
// When this token is resolved, it will wrap itself in a group, so we don't want the resolver to group wrap it again.
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
constructor({ name = null, capturing = true } = {}, tokens = []) {
|
|
34
|
+
super();
|
|
35
|
+
this._name = null;
|
|
36
|
+
this._capturing = true;
|
|
37
|
+
this.name = name;
|
|
38
|
+
this.capturing = capturing;
|
|
39
|
+
if (tokens instanceof collection_1.RGXTokenCollection && tokens.mode === 'union')
|
|
40
|
+
this.tokens = new collection_1.RGXTokenCollection(tokens, 'concat');
|
|
41
|
+
else
|
|
42
|
+
this.tokens = new collection_1.RGXTokenCollection(tokens, 'concat');
|
|
43
|
+
}
|
|
44
|
+
toRgx() {
|
|
45
|
+
// The collection token doesn't group itself, so this is safe.
|
|
46
|
+
let result = this.tokens.toRgx().source;
|
|
47
|
+
if (this.name !== null)
|
|
48
|
+
result = `(?<${this.name}>${result})`;
|
|
49
|
+
else if (!this.capturing)
|
|
50
|
+
result = `(?:${result})`;
|
|
51
|
+
else
|
|
52
|
+
result = `(${result})`;
|
|
53
|
+
return new RegExp(result);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.RGXGroupToken = RGXGroupToken;
|
|
57
|
+
RGXGroupToken.check = (0, internal_1.createClassGuardFunction)(RGXGroupToken);
|
|
58
|
+
RGXGroupToken.assert = (0, internal_1.createAssertClassGuardFunction)(RGXGroupToken);
|
|
59
|
+
exports.rgxGroup = (0, internal_1.createConstructFunction)(RGXGroupToken);
|
package/dist/class/index.d.ts
CHANGED
package/dist/class/index.js
CHANGED
package/dist/class/init.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.rgxClassInit = rgxClassInit;
|
|
4
4
|
const base_1 = require("./base");
|
|
5
5
|
const union_1 = require("./union");
|
|
6
|
+
const group_1 = require("./group");
|
|
6
7
|
function rgxClassInit() {
|
|
7
8
|
// Patch RGXClassToken here, Since classes like RGXClassUnionToken are instances of RGXClassToken
|
|
8
9
|
// themselves. If we tried to import RGXClassUnionToken in base.ts, it would cause a circular dependency.
|
|
@@ -19,4 +20,7 @@ function rgxClassInit() {
|
|
|
19
20
|
return new union_1.RGXClassUnionToken([this, ...filteredOthers]);
|
|
20
21
|
}
|
|
21
22
|
};
|
|
23
|
+
base_1.RGXClassToken.prototype.group = function (args = {}) {
|
|
24
|
+
return new group_1.RGXGroupToken(args, [this]);
|
|
25
|
+
};
|
|
22
26
|
}
|
package/dist/collection.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RGXToken } from "./types";
|
|
1
|
+
import { RGXToken, ValidRegexString } from "./types";
|
|
2
2
|
import { CloneDepth } from "@ptolemy2002/immutability-utils";
|
|
3
3
|
import { Collection } from "@ptolemy2002/ts-utils";
|
|
4
4
|
export type RGXTokenCollectionMode = 'union' | 'concat';
|
|
@@ -9,6 +9,7 @@ export declare class RGXTokenCollection implements Collection<RGXToken> {
|
|
|
9
9
|
static check: (value: unknown) => value is RGXTokenCollection;
|
|
10
10
|
static assert: (value: unknown) => asserts value is RGXTokenCollection;
|
|
11
11
|
constructor(tokens?: RGXTokenCollectionInput, mode?: RGXTokenCollectionMode);
|
|
12
|
+
resolve(): ValidRegexString;
|
|
12
13
|
toRgx(): RegExp;
|
|
13
14
|
getTokens(): RGXToken[];
|
|
14
15
|
clone(depth?: CloneDepth): RGXTokenCollection;
|
package/dist/collection.js
CHANGED
package/dist/errors/base.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED';
|
|
1
|
+
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS';
|
|
2
2
|
export declare class RGXError extends Error {
|
|
3
3
|
code: RGXErrorCode;
|
|
4
4
|
constructor(message: string, code?: RGXErrorCode);
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -19,3 +19,5 @@ __exportStar(require("./invalidToken"), exports);
|
|
|
19
19
|
__exportStar(require("./invalidRegexString"), exports);
|
|
20
20
|
__exportStar(require("./invalidVanillaRegexFlags"), exports);
|
|
21
21
|
__exportStar(require("./notImplemented"), exports);
|
|
22
|
+
__exportStar(require("./invalidIdentifier"), exports);
|
|
23
|
+
__exportStar(require("./outOfBounds"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXInvalidIdentifierError = void 0;
|
|
4
|
+
const errors_1 = require("./");
|
|
5
|
+
class RGXInvalidIdentifierError extends errors_1.RGXError {
|
|
6
|
+
constructor(message, got) {
|
|
7
|
+
super(message, 'INVALID_IDENTIFIER');
|
|
8
|
+
this.name = 'RGXInvalidIdentifierError';
|
|
9
|
+
this.got = got;
|
|
10
|
+
}
|
|
11
|
+
toString() {
|
|
12
|
+
return `${this.name}: ${this.message}; Got: ${JSON.stringify(this.got)}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.RGXInvalidIdentifierError = RGXInvalidIdentifierError;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RGXError } from "./base";
|
|
2
|
+
import { RangeObject } from "../types";
|
|
3
|
+
export declare class RGXOutOfBoundsError extends RGXError {
|
|
4
|
+
got: number;
|
|
5
|
+
_min: number | null;
|
|
6
|
+
_max: number | null;
|
|
7
|
+
inclusiveLeft: boolean;
|
|
8
|
+
inclusiveRight: boolean;
|
|
9
|
+
get min(): number | null;
|
|
10
|
+
set min(value: number | null);
|
|
11
|
+
get max(): number | null;
|
|
12
|
+
set max(value: number | null);
|
|
13
|
+
constructor(message: string, got: number, { min, max, inclusiveLeft, inclusiveRight }?: RangeObject);
|
|
14
|
+
failedAtMin(): boolean;
|
|
15
|
+
failedAtMax(): boolean;
|
|
16
|
+
failedAtAny(): boolean;
|
|
17
|
+
toString(): string;
|
|
18
|
+
}
|
|
19
|
+
export declare function isInRange(value: number, { min, max, inclusiveLeft, inclusiveRight }?: RangeObject): boolean;
|
|
20
|
+
export declare function assertInRange(value: number, range: RangeObject, message?: string): void;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXOutOfBoundsError = void 0;
|
|
4
|
+
exports.isInRange = isInRange;
|
|
5
|
+
exports.assertInRange = assertInRange;
|
|
6
|
+
const base_1 = require("./base");
|
|
7
|
+
class RGXOutOfBoundsError extends base_1.RGXError {
|
|
8
|
+
get min() {
|
|
9
|
+
return this._min;
|
|
10
|
+
}
|
|
11
|
+
set min(value) {
|
|
12
|
+
this._min = value;
|
|
13
|
+
if (this._max !== null && value !== null && value > this._max) {
|
|
14
|
+
this._max = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
get max() {
|
|
18
|
+
return this._max;
|
|
19
|
+
}
|
|
20
|
+
set max(value) {
|
|
21
|
+
this._max = value;
|
|
22
|
+
if (this._min !== null && value !== null && value < this._min) {
|
|
23
|
+
this._min = value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
constructor(message, got, { min = null, max = null, inclusiveLeft = true, inclusiveRight = true } = {}) {
|
|
27
|
+
super(message, 'OUT_OF_BOUNDS');
|
|
28
|
+
this.name = 'RGXOutOfBoundsError';
|
|
29
|
+
this.got = got;
|
|
30
|
+
this.min = min;
|
|
31
|
+
this.max = max;
|
|
32
|
+
this.inclusiveLeft = inclusiveLeft;
|
|
33
|
+
this.inclusiveRight = inclusiveRight;
|
|
34
|
+
}
|
|
35
|
+
failedAtMin() {
|
|
36
|
+
return this.min !== null && (this.inclusiveLeft ? this.got < this.min : this.got <= this.min);
|
|
37
|
+
}
|
|
38
|
+
failedAtMax() {
|
|
39
|
+
return this.max !== null && (this.inclusiveRight ? this.got > this.max : this.got >= this.max);
|
|
40
|
+
}
|
|
41
|
+
failedAtAny() {
|
|
42
|
+
return this.failedAtMin() || this.failedAtMax();
|
|
43
|
+
}
|
|
44
|
+
toString() {
|
|
45
|
+
const rangeParts = [];
|
|
46
|
+
if (this.min !== null) {
|
|
47
|
+
if (this.inclusiveLeft)
|
|
48
|
+
rangeParts.push(`>= ${this.min}`);
|
|
49
|
+
else
|
|
50
|
+
rangeParts.push(`> ${this.min}`);
|
|
51
|
+
}
|
|
52
|
+
if (this.max !== null) {
|
|
53
|
+
if (this.inclusiveRight)
|
|
54
|
+
rangeParts.push(`<= ${this.max}`);
|
|
55
|
+
else
|
|
56
|
+
rangeParts.push(`< ${this.max}`);
|
|
57
|
+
}
|
|
58
|
+
const rangeStr = rangeParts.join(" and ");
|
|
59
|
+
// Determine which one was failed
|
|
60
|
+
if (!this.failedAtAny()) {
|
|
61
|
+
return `${this.name}: ${this.message}; Got: [${this.got}]; Expected: [${rangeStr}]`;
|
|
62
|
+
}
|
|
63
|
+
else if (this.failedAtMin()) {
|
|
64
|
+
let thirdPart;
|
|
65
|
+
if (!this.inclusiveLeft && this.got === this.min)
|
|
66
|
+
thirdPart = `${this.got} == ${this.min}`;
|
|
67
|
+
else
|
|
68
|
+
thirdPart = `${this.got} < ${this.min}`;
|
|
69
|
+
return `${this.name}: ${this.message}; Got: [${this.got}]; Expected: [${rangeStr}]; ${thirdPart}`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
let thirdPart;
|
|
73
|
+
if (!this.inclusiveRight && this.got === this.max)
|
|
74
|
+
thirdPart = `${this.got} == ${this.max}`;
|
|
75
|
+
else
|
|
76
|
+
thirdPart = `${this.got} > ${this.max}`;
|
|
77
|
+
return `${this.name}: ${this.message}; Got: [${this.got}]; Expected: [${rangeStr}]; ${thirdPart}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.RGXOutOfBoundsError = RGXOutOfBoundsError;
|
|
82
|
+
function isInRange(value, { min = null, max = null, inclusiveLeft = true, inclusiveRight = true } = {}) {
|
|
83
|
+
if (min !== null) {
|
|
84
|
+
if (inclusiveLeft) {
|
|
85
|
+
if (value < min)
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
if (value <= min)
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (max !== null) {
|
|
94
|
+
if (inclusiveRight) {
|
|
95
|
+
if (value > max)
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (value >= max)
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
function assertInRange(value, range, message = "Value out of bounds") {
|
|
106
|
+
if (!isInRange(value, range)) {
|
|
107
|
+
throw new RGXOutOfBoundsError(message, value, range);
|
|
108
|
+
}
|
|
109
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export * from "./collection";
|
|
|
6
6
|
export * from "./class";
|
|
7
7
|
export * from "./resolve";
|
|
8
8
|
export * from "./concat";
|
|
9
|
+
export * from "./utils";
|
|
9
10
|
export declare function rgxa(tokens: t.RGXToken[], flags?: string): RegExp;
|
|
10
11
|
export default function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => RegExp;
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ __exportStar(require("./collection"), exports);
|
|
|
49
49
|
__exportStar(require("./class"), exports);
|
|
50
50
|
__exportStar(require("./resolve"), exports);
|
|
51
51
|
__exportStar(require("./concat"), exports);
|
|
52
|
+
__exportStar(require("./utils"), exports);
|
|
52
53
|
// Call this for certain class methods to work correctly
|
|
53
54
|
(0, class_1.rgxClassInit)();
|
|
54
55
|
function rgxa(tokens, flags = '') {
|
package/dist/resolve.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import * as t from "./types";
|
|
2
2
|
export declare function escapeRegex(value: string): t.ValidRegexString;
|
|
3
|
-
export declare function resolveRGXToken(token: t.RGXToken, groupWrap?: boolean): t.ValidRegexString;
|
|
3
|
+
export declare function resolveRGXToken(token: t.RGXToken, groupWrap?: boolean, topLevel?: boolean): t.ValidRegexString;
|
package/dist/resolve.js
CHANGED
|
@@ -41,7 +41,7 @@ const tg = __importStar(require("./typeGuards"));
|
|
|
41
41
|
function escapeRegex(value) {
|
|
42
42
|
return value.replaceAll(/[\-\^\$.*+?^${}()|[\]\\]/g, '\\$&');
|
|
43
43
|
}
|
|
44
|
-
function resolveRGXToken(token, groupWrap = true) {
|
|
44
|
+
function resolveRGXToken(token, groupWrap = true, topLevel = true) {
|
|
45
45
|
if (tg.isRGXNoOpToken(token))
|
|
46
46
|
return '';
|
|
47
47
|
if (tg.isRGXLiteralToken(token)) {
|
|
@@ -53,7 +53,9 @@ function resolveRGXToken(token, groupWrap = true) {
|
|
|
53
53
|
if (tg.isRGXNativeToken(token))
|
|
54
54
|
return escapeRegex(String(token));
|
|
55
55
|
if (tg.isRGXConvertibleToken(token)) {
|
|
56
|
-
|
|
56
|
+
// The top-level group-wrapping preference propogates to a direct convertible token, but after that
|
|
57
|
+
// the preference falls back to true whenever a token doesn't explicitly specify a preference.
|
|
58
|
+
return resolveRGXToken(token.toRgx(), token.rgxGroupWrap ?? (topLevel ? groupWrap : true), false);
|
|
57
59
|
}
|
|
58
60
|
// Interpret arrays as unions
|
|
59
61
|
if (tg.isRGXArrayToken(token, false)) {
|
|
@@ -64,9 +66,9 @@ function resolveRGXToken(token, groupWrap = true) {
|
|
|
64
66
|
token = [...(0, class_1.removeRgxUnionDuplicates)(...token)];
|
|
65
67
|
// Don't preserve group wrapping preference for the recursive calls
|
|
66
68
|
if (groupWrap)
|
|
67
|
-
return '(?:' + token.map(t => resolveRGXToken(t, true)).join('|') + ')';
|
|
69
|
+
return '(?:' + token.map(t => resolveRGXToken(t, true, false)).join('|') + ')';
|
|
68
70
|
else
|
|
69
|
-
return token.map(t => resolveRGXToken(t, true)).join('|');
|
|
71
|
+
return token.map(t => resolveRGXToken(t, true, false)).join('|');
|
|
70
72
|
}
|
|
71
73
|
return resolveRGXToken(token[0]);
|
|
72
74
|
}
|
package/dist/typeGuards.d.ts
CHANGED
|
@@ -20,3 +20,5 @@ export declare function isValidRegexString(value: string): value is t.ValidRegex
|
|
|
20
20
|
export declare function assertValidRegexString(value: string): asserts value is t.ValidRegexString;
|
|
21
21
|
export declare function isValidVanillaRegexFlags(value: string): value is t.ValidVanillaRegexFlags;
|
|
22
22
|
export declare function assertValidVanillaRegexFlags(value: string): asserts value is t.ValidVanillaRegexFlags;
|
|
23
|
+
export declare function isValidIdentifier(value: string): value is t.ValidIdentifier;
|
|
24
|
+
export declare function assertValidIdentifier(value: string): asserts value is t.ValidIdentifier;
|
package/dist/typeGuards.js
CHANGED
|
@@ -57,6 +57,8 @@ exports.isValidRegexString = isValidRegexString;
|
|
|
57
57
|
exports.assertValidRegexString = assertValidRegexString;
|
|
58
58
|
exports.isValidVanillaRegexFlags = isValidVanillaRegexFlags;
|
|
59
59
|
exports.assertValidVanillaRegexFlags = assertValidVanillaRegexFlags;
|
|
60
|
+
exports.isValidIdentifier = isValidIdentifier;
|
|
61
|
+
exports.assertValidIdentifier = assertValidIdentifier;
|
|
60
62
|
const e = __importStar(require("./errors"));
|
|
61
63
|
const is_callable_1 = __importDefault(require("is-callable"));
|
|
62
64
|
const internal_1 = require("./internal");
|
|
@@ -87,6 +89,9 @@ function assertRGXNativeToken(value) {
|
|
|
87
89
|
}
|
|
88
90
|
function isRGXConvertibleToken(value, returnCheck = true) {
|
|
89
91
|
if (typeof value === 'object' && value !== null && 'toRgx' in value) {
|
|
92
|
+
// The rgxGroupWrap property is optional, but if it exists it must be a boolean.
|
|
93
|
+
if ('rgxGroupWrap' in value && typeof value.rgxGroupWrap !== 'boolean')
|
|
94
|
+
return false;
|
|
90
95
|
if ((0, is_callable_1.default)(value.toRgx)) {
|
|
91
96
|
if (!returnCheck)
|
|
92
97
|
return true;
|
|
@@ -215,3 +220,12 @@ function assertValidVanillaRegexFlags(value) {
|
|
|
215
220
|
throw new e.RGXInvalidVanillaRegexFlagsError("Invalid vanilla regex flags", value);
|
|
216
221
|
}
|
|
217
222
|
}
|
|
223
|
+
function isValidIdentifier(value) {
|
|
224
|
+
// This regex checks for valid JavaScript identifiers, which can be used for named capture groups.
|
|
225
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
|
|
226
|
+
}
|
|
227
|
+
function assertValidIdentifier(value) {
|
|
228
|
+
if (!isValidIdentifier(value)) {
|
|
229
|
+
throw new e.RGXInvalidIdentifierError("Invalid identifier", value);
|
|
230
|
+
}
|
|
231
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type RGXLiteralToken = RegExp;
|
|
|
5
5
|
export type RGXNativeToken = string | number | boolean | RGXNoOpToken;
|
|
6
6
|
export type RGXConvertibleToken = {
|
|
7
7
|
toRgx: () => RGXToken;
|
|
8
|
+
readonly rgxGroupWrap?: boolean;
|
|
8
9
|
};
|
|
9
10
|
export type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken | RGXToken[];
|
|
10
11
|
export type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
|
|
@@ -14,9 +15,18 @@ export type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenCons
|
|
|
14
15
|
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 RGXTokenTypeGuardInput[] ? {
|
|
15
16
|
[K in keyof T]: T[K] extends RGXTokenTypeGuardInput ? RGXTokenFromType<T[K]> : never;
|
|
16
17
|
} : T extends RGXClassTokenConstructor ? InstanceType<T> : never;
|
|
18
|
+
export type RangeObject = {
|
|
19
|
+
min?: number | null;
|
|
20
|
+
max?: number | null;
|
|
21
|
+
inclusiveLeft?: boolean;
|
|
22
|
+
inclusiveRight?: boolean;
|
|
23
|
+
};
|
|
17
24
|
export declare const validRegexSymbol: unique symbol;
|
|
18
25
|
export type ValidRegexBrandSymbol = typeof validRegexSymbol;
|
|
19
26
|
export type ValidRegexString = Branded<string, [ValidRegexBrandSymbol]>;
|
|
20
27
|
export declare const validVanillaRegexFlagsSymbol: unique symbol;
|
|
21
28
|
export type ValidVanillaRegexFlagsBrandSymbol = typeof validVanillaRegexFlagsSymbol;
|
|
22
29
|
export type ValidVanillaRegexFlags = Branded<string, [ValidVanillaRegexFlagsBrandSymbol]>;
|
|
30
|
+
export declare const validIdentifierSymbol: unique symbol;
|
|
31
|
+
export type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
|
|
32
|
+
export type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
|
|
3
|
+
exports.validIdentifierSymbol = exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
|
|
4
4
|
exports.validRegexSymbol = Symbol('rgx.ValidRegex');
|
|
5
5
|
exports.validVanillaRegexFlagsSymbol = Symbol('rgx.ValidVanillaRegexFlags');
|
|
6
|
+
exports.validIdentifierSymbol = Symbol('rgx.ValidIdentifier');
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./regexMatchAtPosition"), exports);
|
|
18
|
+
__exportStar(require("./regexWithFlags"), exports);
|
|
19
|
+
__exportStar(require("./normalizeRegexFlags"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function normalizeVanillaRegexFlags(flags: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeVanillaRegexFlags = normalizeVanillaRegexFlags;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
function normalizeVanillaRegexFlags(flags) {
|
|
6
|
+
const validFlags = ['g', 'i', 'm', 's', 'u', 'y'];
|
|
7
|
+
const seenFlags = new Set();
|
|
8
|
+
let normalizedFlags = '';
|
|
9
|
+
for (const flag of flags) {
|
|
10
|
+
if (!validFlags.includes(flag)) {
|
|
11
|
+
throw new errors_1.RGXInvalidVanillaRegexFlagsError(`[${flag}] is not valid.`, flags);
|
|
12
|
+
}
|
|
13
|
+
if (!seenFlags.has(flag)) {
|
|
14
|
+
seenFlags.add(flag);
|
|
15
|
+
normalizedFlags += flag;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return normalizedFlags;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function regexMatchAtPosition(regex: RegExp, str: string, position: number): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.regexMatchAtPosition = regexMatchAtPosition;
|
|
4
|
+
const outOfBounds_1 = require("../errors/outOfBounds");
|
|
5
|
+
const regexWithFlags_1 = require("./regexWithFlags");
|
|
6
|
+
function regexMatchAtPosition(regex, str, position) {
|
|
7
|
+
/*
|
|
8
|
+
The y flag means sticky mode, which means the next match must start at
|
|
9
|
+
lastIndex. By setting lastIndex to the position we want to check, we can test
|
|
10
|
+
if the regex matches at that position.
|
|
11
|
+
*/
|
|
12
|
+
(0, outOfBounds_1.assertInRange)(position, { min: 0, max: str.length, inclusiveRight: false }, 'String index out of bounds');
|
|
13
|
+
const stickyRegex = (0, regexWithFlags_1.regexWithFlags)(regex, "y");
|
|
14
|
+
stickyRegex.lastIndex = position;
|
|
15
|
+
return stickyRegex.test(str);
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function regexWithFlags(exp: RegExp, flags: string, replace?: boolean): RegExp;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.regexWithFlags = regexWithFlags;
|
|
4
|
+
const typeGuards_1 = require("../typeGuards");
|
|
5
|
+
const normalizeRegexFlags_1 = require("./normalizeRegexFlags");
|
|
6
|
+
function regexWithFlags(exp, flags, replace = false) {
|
|
7
|
+
(0, typeGuards_1.assertValidVanillaRegexFlags)(flags);
|
|
8
|
+
if (replace)
|
|
9
|
+
return new RegExp(exp.source, flags);
|
|
10
|
+
const existingFlags = exp.flags;
|
|
11
|
+
const newFlags = existingFlags + flags;
|
|
12
|
+
return new RegExp(exp.source, (0, normalizeRegexFlags_1.normalizeVanillaRegexFlags)(newFlags));
|
|
13
|
+
}
|