@ptolemy2002/rgx 4.2.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,21 +20,28 @@ const validVanillaRegexFlagsSymbol = Symbol('rgx.ValidVanillaRegexFlags');
20
20
  type ValidVanillaRegexFlagsBrandSymbol = typeof validVanillaRegexFlagsSymbol;
21
21
  type ValidVanillaRegexFlags = Branded<string, [ValidVanillaRegexFlagsBrandSymbol]>;
22
22
 
23
+ const validRegexFlagsSymbol = Symbol('rgx.ValidRegexFlags');
24
+ type ValidRegexFlagsBrandSymbol = typeof validRegexFlagsSymbol;
25
+ type ValidRegexFlags = Branded<string, [ValidRegexFlagsBrandSymbol]> | ValidVanillaRegexFlags;
26
+
27
+ type RegExpFlagTransformer = (exp: RegExp) => RegExp;
28
+
23
29
  const validIdentifierSymbol = Symbol('rgx.ValidIdentifier');
24
30
  type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
25
31
  type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
26
32
 
27
33
  type RGXTokenType = 'no-op' | 'literal' | 'native' | 'convertible' | 'class' | RGXTokenType[];
28
34
  type RGXTokenTypeFlat = Exclude<RGXTokenType, RGXTokenType[]> | "array";
29
- type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | RGXTokenTypeGuardInput[];
35
+ type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
30
36
  type RGXTokenFromType<T extends RGXTokenTypeGuardInput> =
31
37
  // Maps token type strings to their corresponding types, e.g.:
32
38
  // 'no-op' -> RGXNoOpToken, 'literal' -> RGXLiteralToken, etc.
33
- // Also maps RGXClassTokenConstructor to InstanceType<T>.
39
+ // Also maps any constructor to InstanceType<T>,
40
+ // and preserves tuple types for constant arrays.
34
41
  // ... see source for full definition
35
42
  ;
36
43
 
37
- type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS';
44
+ type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT';
38
45
 
39
46
  type RangeObject = {
40
47
  min?: number | null;
@@ -149,6 +156,54 @@ constructor(message: string, got: string)
149
156
  #### Methods
150
157
  - `toString() => string`: Returns a formatted string indicating the invalid identifier and the reason for failure.
151
158
 
159
+ ### RGXInvalidRegexFlagsError extends RGXError
160
+ A specific error class for invalid regex flags (including both vanilla and custom registered flags). This error is thrown when a string fails validation as valid regex flags. The error code is set to `INVALID_REGEX_FLAGS` on instantiation.
161
+
162
+ #### Constructor
163
+ ```typescript
164
+ constructor(message: string, got: string)
165
+ ```
166
+ - `message` (`string`): The error message.
167
+ - `got` (`string`): The actual string that was received, which failed validation.
168
+
169
+ #### Properties
170
+ - `got` (`string`): The actual string that was received, which failed validation.
171
+
172
+ #### Methods
173
+ - `toString() => string`: Returns a formatted string indicating the invalid flags and the reason for failure.
174
+
175
+ ### RGXInvalidFlagTransformerKeyError extends RGXError
176
+ A specific error class for invalid flag transformer keys. This error is thrown when an invalid key is provided to `registerFlagTransformer` (e.g., a key that is not a single character). The error code is set to `INVALID_FLAG_TRANSFORMER_KEY` on instantiation.
177
+
178
+ #### Constructor
179
+ ```typescript
180
+ constructor(message: string, got: string)
181
+ ```
182
+ - `message` (`string`): The error message.
183
+ - `got` (`string`): The actual key string that was received, which failed validation.
184
+
185
+ #### Properties
186
+ - `got` (`string`): The actual key string that was received, which failed validation.
187
+
188
+ #### Methods
189
+ - `toString() => string`: Returns a formatted string indicating the invalid key and the reason for failure.
190
+
191
+ ### RGXFlagTransformerConflictError extends RGXError
192
+ A specific error class for flag transformer conflicts. This error is thrown when attempting to register a flag transformer with a key that conflicts with an existing vanilla regex flag or an already-registered transformer. The error code is set to `FLAG_TRANSFORMER_CONFLICT` on instantiation.
193
+
194
+ #### Constructor
195
+ ```typescript
196
+ constructor(message: string, got: string)
197
+ ```
198
+ - `message` (`string`): The error message.
199
+ - `got` (`string`): The conflicting key string.
200
+
201
+ #### Properties
202
+ - `got` (`string`): The conflicting key string.
203
+
204
+ #### Methods
205
+ - `toString() => string`: Returns a formatted string indicating the conflict and the reason for failure.
206
+
152
207
  ### RGXOutOfBoundsError extends RGXError
153
208
  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
209
 
@@ -277,6 +332,24 @@ constructor(args?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput)
277
332
  #### Methods
278
333
  - `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
334
 
335
+ ### ExtRegExp extends RegExp
336
+ A subclass of `RegExp` that supports custom flag transformers in addition to the standard vanilla regex flags (g, i, m, s, u, y). When constructed, custom flags are extracted, their corresponding transformers are applied to the pattern and vanilla flags, and the resulting transformed `RegExp` is created. The `flags` getter returns both the vanilla flags and any custom flags.
337
+
338
+ A function `extRegExp` is provided with the same parameters as this class' constructor, for easier instantiation without needing to use the `new` keyword.
339
+
340
+ #### Constructor
341
+ ```typescript
342
+ constructor(pattern: string | RegExp, flags?: string)
343
+ ```
344
+ - `pattern` (`string | RegExp`): The regex pattern. If a `RegExp` is provided, its `source` is used and its existing `flags` are tracked as already-applied flags to avoid re-applying transformers.
345
+ - `flags` (`string`, optional): The flags string, which may include both vanilla regex flags and custom registered flag keys. Validated via `assertValidRegexFlags`. Defaults to `''`.
346
+
347
+ #### Properties
348
+ - `flags` (`string`): Returns the combination of the vanilla flags (from the underlying `RegExp`) and any custom flags that were applied during construction.
349
+
350
+ #### Static Properties
351
+ - `[Symbol.species]` (`RegExpConstructor`): Returns `ExtRegExp`, ensuring that derived `RegExp` methods (like those returning new regex instances) produce `ExtRegExp` instances rather than plain `RegExp`.
352
+
280
353
  ## Functions
281
354
  The following functions are exported by the library:
282
355
 
@@ -659,10 +732,10 @@ A helper function that resolves an array of RGX tokens and concatenates their re
659
732
 
660
733
  ### rgx
661
734
  ```typescript
662
- function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: RGXToken[]) => RegExp
735
+ function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: RGXToken[]) => ExtRegExp
663
736
  ```
664
737
 
665
- Creates and returns a template tag function that constructs a `RegExp` 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.
738
+ 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.
666
739
 
667
740
  Example usages:
668
741
  ```typescript
@@ -679,27 +752,27 @@ const pattern3 = rgx()`${beginning}value: ${[word, optionalDigit]}${end}`; // /^
679
752
 
680
753
  #### Parameters
681
754
  **Direct**
682
- - `flags` (`string`, optional): The regex flags to apply to the resulting `RegExp` object (e.g., 'g', 'i', 'm', etc.). If not provided, no flags will be applied. If provided and not valid vanilla regex flags, an `RGXInvalidVanillaRegexFlagsError` will be thrown.
755
+ - `flags` (`string`, optional): The regex flags to apply to the resulting `ExtRegExp` object (e.g., 'g', 'i', 'm', or custom registered flags). If not provided, no flags will be applied. If provided and not valid regex flags (vanilla or registered custom), an `RGXInvalidRegexFlagsError` will be thrown.
683
756
 
684
757
  **Template Tag**
685
758
  - `strings` (`TemplateStringsArray`): The literal parts of the template string.
686
759
  - `tokens` (`RGXToken[]`): The RGX tokens to be resolved and concatenated with the literal parts.
687
760
 
688
761
  #### Returns
689
- - `(strings: TemplateStringsArray, ...tokens: RGXToken[]) => RegExp`: A template tag function that takes a template literal and returns a `RegExp` object constructed from the resolved tokens, literal parts, and the provided flags.
762
+ - `(strings: TemplateStringsArray, ...tokens: RGXToken[]) => ExtRegExp`: A template tag function that takes a template literal and returns an `ExtRegExp` object constructed from the resolved tokens, literal parts, and the provided flags.
690
763
 
691
764
  ### rgxa
692
765
  ```typescript
693
- function rgxa(tokens: RGXToken[], flags?: string): RegExp
766
+ function rgxa(tokens: RGXToken[], flags?: string): ExtRegExp
694
767
  ```
695
- 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 a `RegExp` object. This is useful in cases where you don't want to use a template literal.
768
+ 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.
696
769
 
697
770
  #### Parameters
698
771
  - `tokens` (`RGXToken[]`): The RGX tokens to be resolved and concatenated to form the regex pattern.
699
- - `flags` (`string`, optional): The regex flags to apply to the resulting `RegExp` object (e.g., 'g', 'i', 'm', etc.). If not provided, no flags will be applied. If provided and not valid vanilla regex flags, an `RGXInvalidVanillaRegexFlagsError` will be thrown.
772
+ - `flags` (`string`, optional): The regex flags to apply to the resulting `ExtRegExp` object (e.g., 'g', 'i', 'm', or custom registered flags). If not provided, no flags will be applied. If provided and not valid regex flags (vanilla or registered custom), an `RGXInvalidRegexFlagsError` will be thrown.
700
773
 
701
774
  #### Returns
702
- - `RegExp`: A `RegExp` object constructed from the resolved tokens and the provided flags.
775
+ - `ExtRegExp`: An `ExtRegExp` object constructed from the resolved tokens and the provided flags.
703
776
 
704
777
  ### expandRgxUnionTokens
705
778
  ```typescript
@@ -766,12 +839,132 @@ Asserts that the given numeric value falls within the specified range. If the as
766
839
  #### Returns
767
840
  - `void`: This function does not return a value, but will throw an error if the assertion fails.
768
841
 
842
+ ### isValidRegexFlags
843
+ ```typescript
844
+ function isValidRegexFlags(flags: string): flags is ValidRegexFlags
845
+ ```
846
+
847
+ Checks if the given string is a valid combination of regex flags, including both vanilla flags (g, i, m, s, u, y) and any custom flags registered via `registerFlagTransformer`. Custom flag characters are stripped before validating the remaining characters as vanilla flags.
848
+
849
+ #### Parameters
850
+ - `flags` (`string`): The string to check.
851
+
852
+ #### Returns
853
+ - `boolean`: `true` if the string is a valid combination of regex flags, otherwise `false`.
854
+
855
+ ### assertValidRegexFlags
856
+ ```typescript
857
+ function assertValidRegexFlags(flags: string): asserts flags is ValidRegexFlags
858
+ ```
859
+
860
+ Asserts that the given string is a valid combination of regex flags, including both vanilla flags and any custom registered flags. If the assertion fails, an `RGXInvalidRegexFlagsError` will be thrown.
861
+
862
+ #### Parameters
863
+ - `flags` (`string`): The string to assert.
864
+
865
+ #### Returns
866
+ - `void`: This function does not return a value, but will throw an error if the assertion fails.
867
+
868
+ ### isFlagKeyAvailable
869
+ ```typescript
870
+ function isFlagKeyAvailable(flags: string): boolean
871
+ ```
872
+
873
+ Checks if the given string is available for use as a custom flag transformer key. Returns `false` if the string is a vanilla regex flag or if any character in the string is already registered as a custom flag transformer.
874
+
875
+ #### Parameters
876
+ - `flags` (`string`): The string to check.
877
+
878
+ #### Returns
879
+ - `boolean`: `true` if the string is available for use as a custom flag key, otherwise `false`.
880
+
881
+ ### registerFlagTransformer
882
+ ```typescript
883
+ function registerFlagTransformer(key: string, transformer: RegExpFlagTransformer): void
884
+ ```
885
+
886
+ Registers a custom flag transformer under the given single-character key. The key must be exactly one character, must not be a vanilla regex flag, and must not already be registered. When an `ExtRegExp` is constructed with this flag character in its flags string, the transformer function will be called with the `RegExp` to transform it.
887
+
888
+ #### Parameters
889
+ - `key` (`string`): A single-character string to use as the flag key. Must not be a vanilla regex flag or an already-registered key.
890
+ - `transformer` (`RegExpFlagTransformer`): A function that takes a `RegExp` and returns a transformed `RegExp`.
891
+
892
+ #### Returns
893
+ - `void`: This function does not return a value, but will throw an `RGXInvalidFlagTransformerKeyError` if the key is not a single character, or an `RGXFlagTransformerConflictError` if the key conflicts with a vanilla flag or an existing transformer.
894
+
895
+ ### unregisterFlagTransformer
896
+ ```typescript
897
+ function unregisterFlagTransformer(key: string): void
898
+ ```
899
+
900
+ Unregisters a previously registered custom flag transformer by its key. If the key was not registered, this is a no-op.
901
+
902
+ #### Parameters
903
+ - `key` (`string`): The flag key to unregister.
904
+
905
+ #### Returns
906
+ - `void`: This function does not return a value.
907
+
908
+ ### applyFlagTransformers
909
+ ```typescript
910
+ function applyFlagTransformers(regex: RegExp, flags: string, alreadyAppliedFlags?: string): RegExp
911
+ ```
912
+
913
+ Applies all registered flag transformers whose keys appear in the given flags string to the provided `RegExp`, returning the resulting transformed `RegExp`. Flags present in `alreadyAppliedFlags` are skipped to avoid re-applying transformers.
914
+
915
+ #### Parameters
916
+ - `regex` (`RegExp`): The regular expression to transform.
917
+ - `flags` (`string`): The flags string containing custom flag characters to apply.
918
+ - `alreadyAppliedFlags` (`string`, optional): A string of flag characters that have already been applied and should be skipped. Defaults to `''`.
919
+
920
+ #### Returns
921
+ - `RegExp`: The transformed `RegExp` after applying all matching flag transformers.
922
+
923
+ ### extractCustomRegexFlags
924
+ ```typescript
925
+ function extractCustomRegexFlags(flags: string): string
926
+ ```
927
+
928
+ Extracts the custom (non-vanilla) flag characters from the given flags string by returning only the characters that correspond to registered flag transformers.
929
+
930
+ #### Parameters
931
+ - `flags` (`string`): The flags string to extract custom flags from.
932
+
933
+ #### Returns
934
+ - `string`: A string containing only the custom flag characters found in the input.
935
+
936
+ ### extractVanillaRegexFlags
937
+ ```typescript
938
+ function extractVanillaRegexFlags(flags: string): string
939
+ ```
940
+
941
+ Extracts the vanilla regex flag characters from the given flags string by removing all characters that correspond to registered flag transformers.
942
+
943
+ #### Parameters
944
+ - `flags` (`string`): The flags string to extract vanilla flags from.
945
+
946
+ #### Returns
947
+ - `string`: A string with all registered custom flag characters removed, leaving only vanilla flags.
948
+
949
+ ### normalizeRegexFlags
950
+ ```typescript
951
+ function normalizeRegexFlags(flags: string): string
952
+ ```
953
+
954
+ Normalizes a string of regex flags (including both vanilla and custom registered flags) by removing duplicate flags while preserving order. If any character in the string is not a valid regex flag (vanilla or registered custom), an `RGXInvalidRegexFlagsError` will be thrown.
955
+
956
+ #### Parameters
957
+ - `flags` (`string`): The flags string to normalize.
958
+
959
+ #### Returns
960
+ - `string`: The normalized flags string with duplicates removed.
961
+
769
962
  ### normalizeVanillaRegexFlags
770
963
  ```typescript
771
964
  function normalizeVanillaRegexFlags(flags: string): string
772
965
  ```
773
966
 
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.
967
+ Normalizes a string of vanilla regex flags by removing duplicate flags while preserving order. First validates that all characters are valid vanilla regex flags (g, i, m, s, u, y), throwing an `RGXInvalidVanillaRegexFlagsError` if any are not, then delegates to `normalizeRegexFlags` for deduplication.
775
968
 
776
969
  #### Parameters
777
970
  - `flags` (`string`): The flags string to normalize.
@@ -781,18 +974,18 @@ Normalizes a string of vanilla regex flags by removing duplicate flags while pre
781
974
 
782
975
  ### regexWithFlags
783
976
  ```typescript
784
- function regexWithFlags(exp: RegExp, flags: string, replace?: boolean): RegExp
977
+ function regexWithFlags(exp: RegExp | ExtRegExp, flags: string, replace?: boolean): ExtRegExp
785
978
  ```
786
979
 
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`.
980
+ Creates a new `ExtRegExp` 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
981
 
789
982
  #### Parameters
790
- - `exp` (`RegExp`): The source regular expression.
983
+ - `exp` (`RegExp | ExtRegExp`): The source regular expression.
791
984
  - `flags` (`string`): The flags to add or replace with. Must be valid vanilla regex flags, or an `RGXInvalidVanillaRegexFlagsError` will be thrown.
792
985
  - `replace` (`boolean`, optional): Whether to replace the existing flags entirely instead of merging. Defaults to `false`.
793
986
 
794
987
  #### Returns
795
- - `RegExp`: A new `RegExp` with the same source pattern and the resulting flags.
988
+ - `ExtRegExp`: A new `ExtRegExp` with the same source pattern and the resulting flags.
796
989
 
797
990
  ### regexMatchAtPosition
798
991
  ```typescript
@@ -829,4 +1022,4 @@ The following commands exist in the project:
829
1022
  - `npm run release-major` - Publishes the library to npm with a major version bump
830
1023
  - `npm run test` - Runs the tests for the library
831
1024
  - `npm run test:watch` - Runs the tests for the library in watch mode
832
- - `npm run test:coverage` - Runs the tests for the library and generates a coverage report
1025
+ - `npm run test:coverage` - Runs the tests for the library and generates a coverage report
@@ -0,0 +1,17 @@
1
+ import { ValidRegexFlags } from "./types";
2
+ export type RegExpFlagTransformer = (exp: RegExp) => RegExp;
3
+ export declare class ExtRegExp extends RegExp {
4
+ private extFlags;
5
+ constructor(pattern: string | RegExp, flags?: string);
6
+ get flags(): string;
7
+ static get [Symbol.species](): RegExpConstructor;
8
+ }
9
+ export declare function isFlagKeyAvailable(flags: string): boolean;
10
+ export declare function registerFlagTransformer(key: string, transformer: RegExpFlagTransformer): void;
11
+ export declare function unregisterFlagTransformer(key: string): void;
12
+ export declare function applyFlagTransformers(regex: RegExp, flags: string, alreadyAppliedFlags?: string): RegExp;
13
+ export declare function extractCustomRegexFlags(flags: string): string;
14
+ export declare function extractVanillaRegexFlags(flags: string): string;
15
+ export declare function isValidRegexFlags(flags: string): flags is ValidRegexFlags;
16
+ export declare function assertValidRegexFlags(flags: string): asserts flags is ValidRegexFlags;
17
+ export declare const extRegExp: (pattern: string | RegExp, flags?: string | undefined) => ExtRegExp;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extRegExp = exports.ExtRegExp = void 0;
4
+ exports.isFlagKeyAvailable = isFlagKeyAvailable;
5
+ exports.registerFlagTransformer = registerFlagTransformer;
6
+ exports.unregisterFlagTransformer = unregisterFlagTransformer;
7
+ exports.applyFlagTransformers = applyFlagTransformers;
8
+ exports.extractCustomRegexFlags = extractCustomRegexFlags;
9
+ exports.extractVanillaRegexFlags = extractVanillaRegexFlags;
10
+ exports.isValidRegexFlags = isValidRegexFlags;
11
+ exports.assertValidRegexFlags = assertValidRegexFlags;
12
+ const errors_1 = require("./errors");
13
+ const internal_1 = require("./internal");
14
+ const typeGuards_1 = require("./typeGuards");
15
+ const flagTransformers = {};
16
+ class ExtRegExp extends RegExp {
17
+ constructor(pattern, flags = '') {
18
+ assertValidRegexFlags(flags);
19
+ const vanillaFlags = extractVanillaRegexFlags(flags);
20
+ const customFlags = extractCustomRegexFlags(flags);
21
+ const source = pattern instanceof RegExp ? pattern.source : pattern;
22
+ const alreadyAppliedFlags = pattern instanceof RegExp ? pattern.flags : '';
23
+ const { source: transformedSource, flags: transformedFlags } = applyFlagTransformers(new RegExp(source, vanillaFlags), customFlags, alreadyAppliedFlags);
24
+ super(transformedSource, transformedFlags);
25
+ this.extFlags = customFlags;
26
+ }
27
+ get flags() {
28
+ return super.flags + this.extFlags;
29
+ }
30
+ // Ensure that methods like .exec(), split(), etc. return instances
31
+ // of ExtRegExp rather than plain RegExp (preserves custom flags)
32
+ static get [Symbol.species]() {
33
+ return ExtRegExp;
34
+ }
35
+ }
36
+ exports.ExtRegExp = ExtRegExp;
37
+ function isFlagKeyAvailable(flags) {
38
+ if ((0, typeGuards_1.isValidVanillaRegexFlags)(flags))
39
+ return false;
40
+ for (const flag in flagTransformers) {
41
+ if (flags.includes(flag))
42
+ return false;
43
+ }
44
+ return true;
45
+ }
46
+ function registerFlagTransformer(key, transformer) {
47
+ if (key.length !== 1)
48
+ throw new errors_1.RGXInvalidFlagTransformerKeyError("Flag key must be a single character.", key);
49
+ if ((0, typeGuards_1.isValidVanillaRegexFlags)(key))
50
+ throw new errors_1.RGXFlagTransformerConflictError("Transformer key conflicts with a vanilla regex flag.", key);
51
+ if (!isFlagKeyAvailable(key))
52
+ throw new errors_1.RGXFlagTransformerConflictError("Transformer already exists under this key.", key);
53
+ flagTransformers[key] = transformer;
54
+ }
55
+ function unregisterFlagTransformer(key) {
56
+ delete flagTransformers[key];
57
+ }
58
+ function applyFlagTransformers(regex, flags, alreadyAppliedFlags = '') {
59
+ for (const flag in flagTransformers) {
60
+ if (flags.includes(flag) && !alreadyAppliedFlags.includes(flag)) {
61
+ regex = flagTransformers[flag](regex);
62
+ alreadyAppliedFlags += flag;
63
+ }
64
+ }
65
+ return regex;
66
+ }
67
+ function extractCustomRegexFlags(flags) {
68
+ let customFlags = '';
69
+ for (const flag in flagTransformers) {
70
+ if (flags.includes(flag)) {
71
+ customFlags += flag;
72
+ }
73
+ }
74
+ return customFlags;
75
+ }
76
+ function extractVanillaRegexFlags(flags) {
77
+ for (const flag in flagTransformers) {
78
+ flags = flags.replaceAll(flag, '');
79
+ }
80
+ return flags;
81
+ }
82
+ function isValidRegexFlags(flags) {
83
+ // Remove all instances of registered flag transformers from the flags string, then
84
+ // check if the remaining flags are valid vanilla regex flags.
85
+ flags = extractVanillaRegexFlags(flags);
86
+ return (0, typeGuards_1.isValidVanillaRegexFlags)(flags);
87
+ }
88
+ function assertValidRegexFlags(flags) {
89
+ if (!isValidRegexFlags(flags)) {
90
+ throw new errors_1.RGXInvalidRegexFlagsError("Invalid regex flags", flags);
91
+ }
92
+ }
93
+ exports.extRegExp = (0, internal_1.createConstructFunction)(ExtRegExp);
@@ -1,4 +1,4 @@
1
- export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS';
1
+ export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT';
2
2
  export declare class RGXError extends Error {
3
3
  code: RGXErrorCode;
4
4
  constructor(message: string, code?: RGXErrorCode);
@@ -0,0 +1,6 @@
1
+ import { RGXError } from "./";
2
+ export declare class RGXFlagTransformerConflictError extends RGXError {
3
+ got: string;
4
+ constructor(message: string, got: string);
5
+ toString(): string;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RGXFlagTransformerConflictError = void 0;
4
+ const errors_1 = require("./");
5
+ class RGXFlagTransformerConflictError extends errors_1.RGXError {
6
+ constructor(message, got) {
7
+ super(message, 'FLAG_TRANSFORMER_CONFLICT');
8
+ this.name = 'RGXFlagTransformerConflictError';
9
+ this.got = got;
10
+ }
11
+ toString() {
12
+ return `${this.name}: ${this.message}; Got: ${JSON.stringify(this.got)}`;
13
+ }
14
+ }
15
+ exports.RGXFlagTransformerConflictError = RGXFlagTransformerConflictError;
@@ -1,7 +1,10 @@
1
1
  export * from './base';
2
2
  export * from './invalidToken';
3
3
  export * from './invalidRegexString';
4
+ export * from './invalidRegexFlags';
4
5
  export * from './invalidVanillaRegexFlags';
5
6
  export * from './notImplemented';
6
7
  export * from './invalidIdentifier';
7
8
  export * from './outOfBounds';
9
+ export * from './invalidFlagTransformerKey';
10
+ export * from './flagTransformerConflict';
@@ -17,7 +17,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./base"), exports);
18
18
  __exportStar(require("./invalidToken"), exports);
19
19
  __exportStar(require("./invalidRegexString"), exports);
20
+ __exportStar(require("./invalidRegexFlags"), exports);
20
21
  __exportStar(require("./invalidVanillaRegexFlags"), exports);
21
22
  __exportStar(require("./notImplemented"), exports);
22
23
  __exportStar(require("./invalidIdentifier"), exports);
23
24
  __exportStar(require("./outOfBounds"), exports);
25
+ __exportStar(require("./invalidFlagTransformerKey"), exports);
26
+ __exportStar(require("./flagTransformerConflict"), exports);
@@ -0,0 +1,6 @@
1
+ import { RGXError } from "./";
2
+ export declare class RGXInvalidFlagTransformerKeyError extends RGXError {
3
+ got: string;
4
+ constructor(message: string, got: string);
5
+ toString(): string;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RGXInvalidFlagTransformerKeyError = void 0;
4
+ const errors_1 = require("./");
5
+ class RGXInvalidFlagTransformerKeyError extends errors_1.RGXError {
6
+ constructor(message, got) {
7
+ super(message, 'INVALID_FLAG_TRANSFORMER_KEY');
8
+ this.name = 'RGXInvalidFlagTransformerKeyError';
9
+ this.got = got;
10
+ }
11
+ toString() {
12
+ return `${this.name}: ${this.message}; Got: ${JSON.stringify(this.got)}`;
13
+ }
14
+ }
15
+ exports.RGXInvalidFlagTransformerKeyError = RGXInvalidFlagTransformerKeyError;
@@ -0,0 +1,6 @@
1
+ import { RGXError } from "./";
2
+ export declare class RGXInvalidRegexFlagsError extends RGXError {
3
+ got: string;
4
+ constructor(message: string, got: string);
5
+ toString(): string;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RGXInvalidRegexFlagsError = void 0;
4
+ const errors_1 = require("./");
5
+ class RGXInvalidRegexFlagsError extends errors_1.RGXError {
6
+ constructor(message, got) {
7
+ super(message, 'INVALID_REGEX_FLAGS');
8
+ this.name = 'RGXInvalidRegexFlagsError';
9
+ this.got = got;
10
+ }
11
+ toString() {
12
+ return `${this.name}: ${this.message}; Got: ${JSON.stringify(this.got)}`;
13
+ }
14
+ }
15
+ exports.RGXInvalidRegexFlagsError = RGXInvalidRegexFlagsError;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as t from "./types";
2
+ import { ExtRegExp } from "./ExtRegExp";
2
3
  export * from "./errors";
3
4
  export * from "./types";
4
5
  export * from "./typeGuards";
@@ -7,5 +8,6 @@ export * from "./class";
7
8
  export * from "./resolve";
8
9
  export * from "./concat";
9
10
  export * from "./utils";
10
- export declare function rgxa(tokens: t.RGXToken[], flags?: string): RegExp;
11
- export default function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => RegExp;
11
+ export * from "./ExtRegExp";
12
+ export declare function rgxa(tokens: t.RGXToken[], flags?: string): ExtRegExp;
13
+ export default function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => ExtRegExp;
package/dist/index.js CHANGED
@@ -10,38 +10,16 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
15
  };
38
16
  Object.defineProperty(exports, "__esModule", { value: true });
39
17
  exports.rgxa = rgxa;
40
18
  exports.default = rgx;
41
- const tg = __importStar(require("./typeGuards"));
42
19
  const class_1 = require("./class");
43
20
  const concat_1 = require("./concat");
44
21
  const internal_1 = require("./internal");
22
+ const ExtRegExp_1 = require("./ExtRegExp");
45
23
  __exportStar(require("./errors"), exports);
46
24
  __exportStar(require("./types"), exports);
47
25
  __exportStar(require("./typeGuards"), exports);
@@ -50,15 +28,16 @@ __exportStar(require("./class"), exports);
50
28
  __exportStar(require("./resolve"), exports);
51
29
  __exportStar(require("./concat"), exports);
52
30
  __exportStar(require("./utils"), exports);
31
+ __exportStar(require("./ExtRegExp"), exports);
53
32
  // Call this for certain class methods to work correctly
54
33
  (0, class_1.rgxClassInit)();
55
34
  function rgxa(tokens, flags = '') {
56
- tg.assertValidVanillaRegexFlags(flags);
35
+ (0, ExtRegExp_1.assertValidRegexFlags)(flags);
57
36
  const pattern = (0, concat_1.rgxConcat)(tokens);
58
- return new RegExp(pattern, flags);
37
+ return (0, ExtRegExp_1.extRegExp)(pattern, flags);
59
38
  }
60
39
  function rgx(flags = '') {
61
- tg.assertValidVanillaRegexFlags(flags);
40
+ (0, ExtRegExp_1.assertValidRegexFlags)(flags);
62
41
  return (strings, ...tokens) => {
63
42
  return rgxa((0, internal_1.taggedTemplateToArray)(strings, tokens), flags);
64
43
  };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Branded } from "@ptolemy2002/ts-brand-utils";
2
2
  import type { RGXClassToken } from "./class";
3
+ import type { ExtRegExp } from "./ExtRegExp";
4
+ import type { RGXTokenCollection } from "./collection";
3
5
  export type RGXNoOpToken = null | undefined;
4
6
  export type RGXLiteralToken = RegExp;
5
7
  export type RGXNativeToken = string | number | boolean | RGXNoOpToken;
@@ -11,10 +13,10 @@ export type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken |
11
13
  export type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
12
14
  export type RGXTokenType = 'no-op' | 'literal' | 'native' | 'convertible' | 'class' | RGXTokenType[];
13
15
  export type RGXTokenTypeFlat = Exclude<RGXTokenType, RGXTokenType[]> | "array";
14
- export type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | RGXTokenTypeGuardInput[];
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[] ? {
16
+ export type RGXTokenTypeGuardInput = RGXTokenTypeFlat | null | RGXClassTokenConstructor | typeof ExtRegExp | typeof RGXTokenCollection | RGXTokenTypeGuardInput[];
17
+ export type RGXTokenFromType<T extends RGXTokenTypeGuardInput> = T extends null ? RGXToken : T extends 'no-op' ? RGXNoOpToken : T extends 'literal' ? RGXLiteralToken : T extends 'native' ? RGXNativeToken : T extends 'convertible' ? RGXConvertibleToken : T extends 'class' ? RGXClassToken : T extends 'array' ? RGXToken[] : T extends new (...args: unknown[]) => infer R ? R : T extends RGXTokenTypeGuardInput[] ? {
16
18
  [K in keyof T]: T[K] extends RGXTokenTypeGuardInput ? RGXTokenFromType<T[K]> : never;
17
- } : T extends RGXClassTokenConstructor ? InstanceType<T> : never;
19
+ } : never;
18
20
  export type RangeObject = {
19
21
  min?: number | null;
20
22
  max?: number | null;
@@ -27,6 +29,9 @@ export type ValidRegexString = Branded<string, [ValidRegexBrandSymbol]>;
27
29
  export declare const validVanillaRegexFlagsSymbol: unique symbol;
28
30
  export type ValidVanillaRegexFlagsBrandSymbol = typeof validVanillaRegexFlagsSymbol;
29
31
  export type ValidVanillaRegexFlags = Branded<string, [ValidVanillaRegexFlagsBrandSymbol]>;
32
+ export declare const validRegexFlagsSymbol: unique symbol;
33
+ export type ValidRegexFlagsBrandSymbol = typeof validRegexFlagsSymbol;
34
+ export type ValidRegexFlags = Branded<string, [ValidRegexFlagsBrandSymbol]> | ValidVanillaRegexFlags;
30
35
  export declare const validIdentifierSymbol: unique symbol;
31
36
  export type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
32
37
  export type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
package/dist/types.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validIdentifierSymbol = exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
3
+ exports.validIdentifierSymbol = exports.validRegexFlagsSymbol = exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
4
4
  exports.validRegexSymbol = Symbol('rgx.ValidRegex');
5
5
  exports.validVanillaRegexFlagsSymbol = Symbol('rgx.ValidVanillaRegexFlags');
6
+ exports.validRegexFlagsSymbol = Symbol('rgx.ValidRegexFlags');
6
7
  exports.validIdentifierSymbol = Symbol('rgx.ValidIdentifier');
@@ -1 +1,2 @@
1
+ export declare function normalizeRegexFlags(flags: string): string;
1
2
  export declare function normalizeVanillaRegexFlags(flags: string): string;
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeRegexFlags = normalizeRegexFlags;
3
4
  exports.normalizeVanillaRegexFlags = normalizeVanillaRegexFlags;
4
5
  const errors_1 = require("../errors");
5
- function normalizeVanillaRegexFlags(flags) {
6
- const validFlags = ['g', 'i', 'm', 's', 'u', 'y'];
6
+ const ExtRegExp_1 = require("../ExtRegExp");
7
+ const typeGuards_1 = require("../typeGuards");
8
+ function normalizeRegexFlags(flags) {
7
9
  const seenFlags = new Set();
8
10
  let normalizedFlags = '';
9
11
  for (const flag of flags) {
10
- if (!validFlags.includes(flag)) {
11
- throw new errors_1.RGXInvalidVanillaRegexFlagsError(`[${flag}] is not valid.`, flags);
12
+ if (!(0, ExtRegExp_1.isValidRegexFlags)(flag)) {
13
+ throw new errors_1.RGXInvalidRegexFlagsError(`[${flag}] is not valid.`, flags);
12
14
  }
13
15
  if (!seenFlags.has(flag)) {
14
16
  seenFlags.add(flag);
@@ -17,3 +19,12 @@ function normalizeVanillaRegexFlags(flags) {
17
19
  }
18
20
  return normalizedFlags;
19
21
  }
22
+ function normalizeVanillaRegexFlags(flags) {
23
+ for (const flag of flags) {
24
+ if (!(0, typeGuards_1.isValidVanillaRegexFlags)(flag)) {
25
+ throw new errors_1.RGXInvalidVanillaRegexFlagsError(`[${flag}] is not a valid vanilla regex flag.`, flags);
26
+ }
27
+ }
28
+ // This will not throw, as all vanilla flags are valid regex flags.
29
+ return normalizeRegexFlags(flags);
30
+ }
@@ -1 +1,2 @@
1
- export declare function regexWithFlags(exp: RegExp, flags: string, replace?: boolean): RegExp;
1
+ import { ExtRegExp } from "../ExtRegExp";
2
+ export declare function regexWithFlags(exp: RegExp | ExtRegExp, flags: string, replace?: boolean): ExtRegExp;
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.regexWithFlags = regexWithFlags;
4
4
  const typeGuards_1 = require("../typeGuards");
5
5
  const normalizeRegexFlags_1 = require("./normalizeRegexFlags");
6
+ const ExtRegExp_1 = require("../ExtRegExp");
6
7
  function regexWithFlags(exp, flags, replace = false) {
7
8
  (0, typeGuards_1.assertValidVanillaRegexFlags)(flags);
8
9
  if (replace)
9
- return new RegExp(exp.source, flags);
10
+ return new ExtRegExp_1.ExtRegExp(exp.source, flags);
10
11
  const existingFlags = exp.flags;
11
12
  const newFlags = existingFlags + flags;
12
- return new RegExp(exp.source, (0, normalizeRegexFlags_1.normalizeVanillaRegexFlags)(newFlags));
13
+ return new ExtRegExp_1.ExtRegExp(exp.source, (0, normalizeRegexFlags_1.normalizeVanillaRegexFlags)(newFlags));
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptolemy2002/rgx",
3
- "version": "4.2.1",
3
+ "version": "4.4.0",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",