@ptolemy2002/rgx 4.4.0 → 4.6.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
@@ -277,7 +277,9 @@ An abstract base class for creating custom RGX token classes. Subclasses must im
277
277
  #### Methods
278
278
  - `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.
279
279
  - `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.
280
- - `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`.
280
+ - `repeat(min?: number, max?: number | null) => RGXRepeatToken`: Wraps this token in an `RGXRepeatToken` with the given repetition bounds. `min` defaults to `1`, `max` defaults to `min`. Pass `null` for `max` to allow unlimited repetitions. This is a convenience method that creates a new `RGXRepeatToken` with `this` as the token.
281
+ - `optional() => RGXRepeatToken`: Shorthand for `repeat(0, 1)`. Wraps this token in an `RGXRepeatToken` that matches the token zero or one times.
282
+ - `resolve() => ValidRegexString`: A convenience method that resolves this token by calling `resolveRGXToken(this)`, returning the resolved regex string representation. Since this method is defined on `RGXClassToken`, it is available on all subclasses including `RGXClassUnionToken`, `RGXGroupToken`, and `RGXRepeatToken`.
281
283
 
282
284
  ### RGXClassUnionToken extends RGXClassToken
283
285
  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.
@@ -296,8 +298,6 @@ constructor(tokens: RGXTokenCollectionInput = [])
296
298
 
297
299
  #### Properties
298
300
  - `tokens` (`RGXTokenCollection`): The internal collection of tokens managed in 'union' mode.
299
- - `isGroup` (`boolean`): Returns `true`, indicating this token represents a group.
300
-
301
301
  #### Methods
302
302
  - `add(token: RGXToken, pos?: RGXUnionInsertionPosition) => this`: Adds a token to the union. The `pos` parameter controls where the token is inserted: `'prefix'` inserts at the beginning, `'suffix'` (default) appends to the end. Returns `this` for chaining.
303
303
  - `concat(pos?: RGXUnionInsertionPosition, ...others: RGXTokenCollectionInput[]) => this`: Concatenates additional tokens into the union. The `pos` parameter controls insertion position: `'suffix'` (default) appends to the end, `'prefix'` prepends to the beginning. Returns `this` for chaining.
@@ -332,6 +332,33 @@ constructor(args?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput)
332
332
  #### Methods
333
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.
334
334
 
335
+ ### RGXRepeatToken extends RGXClassToken
336
+ A class representing a repetition quantifier wrapping an RGX token. This allows specifying how many times a token should be matched (e.g., exactly N times, between N and M times, or unlimited). This is typically created via the `repeat()` or `optional()` methods on `RGXClassToken`, but can also be instantiated directly.
337
+
338
+ A function `rgxRepeat` is provided with the same parameters as this class' constructor, for easier instantiation without needing to use the `new` keyword.
339
+
340
+ #### Static Properties
341
+ - `check(value: unknown): value is RGXRepeatToken`: A type guard that checks if the given value is an instance of `RGXRepeatToken`.
342
+ - `assert(value: unknown): asserts value is RGXRepeatToken`: An assertion that checks if the given value is an instance of `RGXRepeatToken`. If the assertion fails, an `RGXInvalidTokenError` will be thrown.
343
+
344
+ #### Constructor
345
+ ```typescript
346
+ constructor(token: RGXToken, min?: number, max?: number | null)
347
+ ```
348
+ - `token` (`RGXToken`): The token to repeat. If the token is not already a group (i.e., not an array, `RegExp`, or an `RGXClassToken` with `isGroup` set to `true`), it will be automatically wrapped in an `RGXGroupToken`.
349
+ - `min` (`number`, optional): The minimum number of repetitions. Must be >= 0 and <= `max` (when `max` is not `null`). Non-integer values are floored. Defaults to `1`.
350
+ - `max` (`number | null`, optional): The maximum number of repetitions. Must be >= `min` when not `null`. Non-integer values are floored. Pass `null` for unlimited repetitions. Defaults to `min`.
351
+
352
+ #### Properties
353
+ - `token` (`RGXToken`): The token being repeated. Setting this will automatically wrap non-group tokens in an `RGXGroupToken`.
354
+ - `min` (`number`): The minimum number of repetitions. Setting this validates that the value is >= 0 and <= `max` (when `max` is not `null`), and floors non-integer values. Throws `RGXOutOfBoundsError` if validation fails.
355
+ - `max` (`number | null`): The maximum number of repetitions. Setting this validates that the value is >= `min` when not `null`, and floors non-integer values. Pass `null` for unlimited. Throws `RGXOutOfBoundsError` if validation fails.
356
+ - `repeaterSuffix` (`string`): Returns the regex quantifier suffix based on the current `min` and `max` values: `*` for `{0,}`, `+` for `{1,}`, `?` for `{0,1}`, `{n}` for exact repetitions, `{n,}` for minimum-only, `{n,m}` for a range, or an empty string for `{1,1}` (exactly once, no quantifier needed).
357
+ - `rgxGroupWrap` (`boolean`): Returns `false`, since the quantifier suffix binds tightly to the preceding group and does not need additional wrapping.
358
+
359
+ #### Methods
360
+ - `toRgx() => RGXToken`: Resolves the repeat token to a `RegExp` by resolving the inner token and appending the `repeaterSuffix`. Returns `null` (a no-op) when both `min` and `max` are `0`.
361
+
335
362
  ### ExtRegExp extends RegExp
336
363
  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
364
 
@@ -805,7 +832,7 @@ Removes duplicate tokens from the provided list using `Set` equality and returns
805
832
  function rgxClassInit(): void
806
833
  ```
807
834
 
808
- 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.
835
+ Initializes internal method patches required for `RGXClassToken` subclass methods (such as `or`, `group`, and `repeat`) 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.
809
836
 
810
837
  ### isInRange
811
838
  ```typescript
@@ -905,6 +932,48 @@ Unregisters a previously registered custom flag transformer by its key. If the k
905
932
  #### Returns
906
933
  - `void`: This function does not return a value.
907
934
 
935
+ ### accentInsensitiveFlagTransformer
936
+ ```typescript
937
+ const accentInsensitiveFlagTransformer: RegExpFlagTransformer
938
+ ```
939
+
940
+ A pre-built `RegExpFlagTransformer` that makes a regex pattern accent-insensitive. It replaces any accentable characters (a, e, i, o, u and their uppercase equivalents) in the regex source with alternation groups that match both the base character and its accented variants. For example, `é` becomes `(e|é|è|ë|ê)`. The following accent mappings are supported:
941
+
942
+ - `a` / `A`: á, à, ä, â, ã / Á, À, Ä, Â, Ã
943
+ - `e` / `E`: é, è, ë, ê / É, È, Ë, Ê
944
+ - `i` / `I`: í, ì, ï, î / Í, Ì, Ï, Î
945
+ - `o` / `O`: ó, ò, ö, ô, õ / Ó, Ò, Ö, Ô, Õ
946
+ - `u` / `U`: ú, ù, ü, û / Ú, Ù, Ü, Û
947
+
948
+ #### Parameters
949
+ - `exp` (`RegExp`): The regular expression to transform.
950
+
951
+ #### Returns
952
+ - `RegExp`: A new `RegExp` with the same flags but with accentable characters in the source replaced by accent-insensitive alternation groups.
953
+
954
+ ### registerCustomFlagTransformers
955
+ ```typescript
956
+ function registerCustomFlagTransformers(): void
957
+ ```
958
+
959
+ Registers the library's built-in custom flag transformers. Currently registers the following:
960
+ - `"a"` flag: `accentInsensitiveFlagTransformer` — makes patterns accent-insensitive.
961
+
962
+ 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.
963
+
964
+ #### Returns
965
+ - `void`: This function does not return a value.
966
+
967
+ ### unregisterCustomFlagTransformers
968
+ ```typescript
969
+ function unregisterCustomFlagTransformers(): void
970
+ ```
971
+
972
+ Unregisters all built-in custom flag transformers that were registered by `registerCustomFlagTransformers`. Currently unregisters the `"a"` flag.
973
+
974
+ #### Returns
975
+ - `void`: This function does not return a value.
976
+
908
977
  ### applyFlagTransformers
909
978
  ```typescript
910
979
  function applyFlagTransformers(regex: RegExp, flags: string, alreadyAppliedFlags?: string): RegExp
@@ -2,6 +2,7 @@ import { RGXToken, ValidRegexString } from "../types";
2
2
  import { RGXTokenCollectionInput } from "../collection";
3
3
  import type { RGXClassUnionToken } from "./union";
4
4
  import type { RGXGroupToken, RGXGroupTokenArgs } from "./group";
5
+ import type { RGXRepeatToken } from "./repeat";
5
6
  export declare abstract class RGXClassToken {
6
7
  abstract toRgx(): RGXToken;
7
8
  static check: (value: unknown) => value is RGXClassToken;
@@ -10,5 +11,7 @@ export declare abstract class RGXClassToken {
10
11
  get rgxGroupWrap(): boolean;
11
12
  or(...others: RGXTokenCollectionInput[]): RGXClassUnionToken;
12
13
  group(args?: RGXGroupTokenArgs): RGXGroupToken;
14
+ repeat(min?: number, max?: number | null): RGXRepeatToken;
15
+ optional(): RGXRepeatToken;
13
16
  resolve(): ValidRegexString;
14
17
  }
@@ -16,6 +16,12 @@ class RGXClassToken {
16
16
  group(args = {}) {
17
17
  throw new errors_1.RGXNotImplementedError('RGXClassToken.group(args)', 'call rgxClassInit() first.');
18
18
  }
19
+ repeat(min = 1, max = min) {
20
+ throw new errors_1.RGXNotImplementedError('RGXClassToken.repeat(min, max)', 'call rgxClassInit() first.');
21
+ }
22
+ optional() {
23
+ return this.repeat(0, 1);
24
+ }
19
25
  resolve() {
20
26
  return (0, resolve_1.resolveRGXToken)(this);
21
27
  }
@@ -2,3 +2,4 @@ export * from "./init";
2
2
  export * from "./base";
3
3
  export * from "./union";
4
4
  export * from "./group";
5
+ export * from "./repeat";
@@ -18,3 +18,4 @@ __exportStar(require("./init"), exports);
18
18
  __exportStar(require("./base"), exports);
19
19
  __exportStar(require("./union"), exports);
20
20
  __exportStar(require("./group"), exports);
21
+ __exportStar(require("./repeat"), exports);
@@ -4,6 +4,7 @@ exports.rgxClassInit = rgxClassInit;
4
4
  const base_1 = require("./base");
5
5
  const union_1 = require("./union");
6
6
  const group_1 = require("./group");
7
+ const repeat_1 = require("./repeat");
7
8
  function rgxClassInit() {
8
9
  // Patch RGXClassToken here, Since classes like RGXClassUnionToken are instances of RGXClassToken
9
10
  // themselves. If we tried to import RGXClassUnionToken in base.ts, it would cause a circular dependency.
@@ -23,4 +24,7 @@ function rgxClassInit() {
23
24
  base_1.RGXClassToken.prototype.group = function (args = {}) {
24
25
  return new group_1.RGXGroupToken(args, [this]);
25
26
  };
27
+ base_1.RGXClassToken.prototype.repeat = function (min = 1, max = min) {
28
+ return new repeat_1.RGXRepeatToken(this, min, max);
29
+ };
26
30
  }
@@ -0,0 +1,20 @@
1
+ import { RGXToken } from "../types";
2
+ import { RGXClassToken } from "./base";
3
+ export declare class RGXRepeatToken extends RGXClassToken {
4
+ _token: RGXToken;
5
+ _min: number;
6
+ _max: number | null;
7
+ static check: (value: unknown) => value is RGXRepeatToken;
8
+ static assert: (value: unknown) => asserts value is RGXRepeatToken;
9
+ get min(): number;
10
+ set min(value: number);
11
+ get max(): number | null;
12
+ set max(value: number | null);
13
+ get token(): RGXToken;
14
+ set token(value: RGXToken);
15
+ get rgxGroupWrap(): boolean;
16
+ constructor(token: RGXToken, min?: number, max?: number | null);
17
+ get repeaterSuffix(): string;
18
+ toRgx(): RGXToken;
19
+ }
20
+ export declare const rgxRepeat: (token: RGXToken, min?: number | undefined, max?: number | null | undefined) => RGXRepeatToken;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rgxRepeat = exports.RGXRepeatToken = void 0;
4
+ const base_1 = require("./base");
5
+ const group_1 = require("./group");
6
+ const typeGuards_1 = require("../typeGuards");
7
+ const errors_1 = require("../errors");
8
+ const resolve_1 = require("../resolve");
9
+ const internal_1 = require("../internal");
10
+ class RGXRepeatToken extends base_1.RGXClassToken {
11
+ get min() {
12
+ return this._min;
13
+ }
14
+ set min(value) {
15
+ (0, errors_1.assertInRange)(value, { min: 0, max: this.max }, "min cannot be negative and cannot be greater than max");
16
+ this._min = Math.floor(value);
17
+ }
18
+ get max() {
19
+ return this._max;
20
+ }
21
+ set max(value) {
22
+ if (value === null) {
23
+ this._max = null;
24
+ return;
25
+ }
26
+ (0, errors_1.assertInRange)(value, { min: Math.max(0, this.min) }, "max cannot be negative and cannot be less than min");
27
+ this._max = Math.floor(value);
28
+ }
29
+ get token() {
30
+ return this._token;
31
+ }
32
+ set token(value) {
33
+ // Arrays and Literals are implicitly grouped.
34
+ const isGroup = (0, typeGuards_1.isRGXToken)(value, "array") ||
35
+ (0, typeGuards_1.isRGXToken)(value, "literal") ||
36
+ ((0, typeGuards_1.isRGXToken)(value, "class") && value.isGroup);
37
+ // Make sure we are always working with a group token.
38
+ if (isGroup)
39
+ this._token = value;
40
+ else
41
+ this._token = new group_1.RGXGroupToken({}, value);
42
+ }
43
+ // We don't need to group wrap this token because the repeater has no
44
+ // semantics that would be lost if there are other tokens to the right.
45
+ get rgxGroupWrap() {
46
+ return false;
47
+ }
48
+ // By default, repeat a fixed number of times.
49
+ constructor(token, min = 1, max = min) {
50
+ super();
51
+ this._max = null;
52
+ this.token = token;
53
+ this.min = min;
54
+ this.max = max;
55
+ }
56
+ get repeaterSuffix() {
57
+ if (this.min === 0 && this.max === null)
58
+ return '*';
59
+ if (this.min === 1 && this.max === null)
60
+ return '+';
61
+ if (this.min === 0 && this.max === 1)
62
+ return '?';
63
+ if (this.max === null)
64
+ return `{${this.min},}`;
65
+ if (this.min === this.max) {
66
+ // No need for a repeater suffix if we're repeating exactly once.
67
+ if (this.min === 1)
68
+ return '';
69
+ return `{${this.min}}`;
70
+ }
71
+ return `{${this.min},${this.max}}`;
72
+ }
73
+ toRgx() {
74
+ // No-op if we're repeating zero times.
75
+ if (this.min === 0 && this.max === 0)
76
+ return null;
77
+ const resolvedSource = (0, resolve_1.resolveRGXToken)(this.token);
78
+ return new RegExp(`${resolvedSource}${this.repeaterSuffix}`);
79
+ }
80
+ }
81
+ exports.RGXRepeatToken = RGXRepeatToken;
82
+ RGXRepeatToken.check = (0, internal_1.createClassGuardFunction)(RGXRepeatToken);
83
+ RGXRepeatToken.assert = (0, internal_1.createAssertClassGuardFunction)(RGXRepeatToken);
84
+ exports.rgxRepeat = (0, internal_1.createConstructFunction)(RGXRepeatToken);
@@ -6,7 +6,6 @@ export declare class RGXClassUnionToken extends RGXClassToken {
6
6
  tokens: RGXTokenCollection;
7
7
  static check: (value: unknown) => value is RGXClassUnionToken;
8
8
  static assert: (value: unknown) => asserts value is RGXClassUnionToken;
9
- get isGroup(): boolean;
10
9
  constructor(tokens?: RGXTokenCollectionInput);
11
10
  cleanTokens(): this;
12
11
  add(token: RGXToken, pos?: RGXUnionInsertionPosition): this;
@@ -7,9 +7,6 @@ const internal_1 = require("../internal");
7
7
  const collection_1 = require("../collection");
8
8
  const base_1 = require("./base");
9
9
  class RGXClassUnionToken extends base_1.RGXClassToken {
10
- get isGroup() {
11
- return true;
12
- }
13
10
  constructor(tokens = []) {
14
11
  super();
15
12
  if (tokens instanceof collection_1.RGXTokenCollection && tokens.mode === 'concat')
@@ -0,0 +1,2 @@
1
+ import { RegExpFlagTransformer } from "../ExtRegExp";
2
+ export declare const accentInsensitiveFlagTransformer: RegExpFlagTransformer;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.accentInsensitiveFlagTransformer = void 0;
4
+ const accentPatterns = [
5
+ "(a|á|à|ä|â|ã)", "(A|Á|À|Ä|Â|Ã)",
6
+ "(e|é|è|ë|ê)", "(E|É|È|Ë|Ê)",
7
+ "(i|í|ì|ï|î)", "(I|Í|Ì|Ï|Î)",
8
+ "(o|ó|ò|ö|ô|õ)", "(O|Ó|Ò|Ö|Ô|Õ)",
9
+ "(u|ú|ù|ü|û)", "(U|Ú|Ù|Ü|Û)"
10
+ ];
11
+ const accentInsensitiveFlagTransformer = function (exp) {
12
+ let source = exp.source;
13
+ const flags = exp.flags;
14
+ accentPatterns.forEach((pattern) => {
15
+ // Replace any of the characters in the pattern with the pattern itself
16
+ source = source.replaceAll(new RegExp(pattern, "g"), pattern);
17
+ });
18
+ return new RegExp(source, flags);
19
+ };
20
+ exports.accentInsensitiveFlagTransformer = accentInsensitiveFlagTransformer;
@@ -0,0 +1,2 @@
1
+ export * from "./accentInsensitive";
2
+ export * from "./register";
@@ -0,0 +1,18 @@
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("./accentInsensitive"), exports);
18
+ __exportStar(require("./register"), exports);
@@ -0,0 +1,2 @@
1
+ export declare function registerCustomFlagTransformers(): void;
2
+ export declare function unregisterCustomFlagTransformers(): void;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCustomFlagTransformers = registerCustomFlagTransformers;
4
+ exports.unregisterCustomFlagTransformers = unregisterCustomFlagTransformers;
5
+ const ExtRegExp_1 = require("../ExtRegExp");
6
+ const accentInsensitive_1 = require("./accentInsensitive");
7
+ function registerCustomFlagTransformers() {
8
+ (0, ExtRegExp_1.registerFlagTransformer)("a", accentInsensitive_1.accentInsensitiveFlagTransformer);
9
+ }
10
+ function unregisterCustomFlagTransformers() {
11
+ (0, ExtRegExp_1.unregisterFlagTransformer)("a");
12
+ }
package/dist/index.d.ts CHANGED
@@ -9,5 +9,6 @@ export * from "./resolve";
9
9
  export * from "./concat";
10
10
  export * from "./utils";
11
11
  export * from "./ExtRegExp";
12
+ export * from "./flag-transformer";
12
13
  export declare function rgxa(tokens: t.RGXToken[], flags?: string): ExtRegExp;
13
14
  export default function rgx(flags?: string): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => ExtRegExp;
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.rgxa = rgxa;
18
18
  exports.default = rgx;
19
19
  const class_1 = require("./class");
20
+ const flag_transformer_1 = require("./flag-transformer");
20
21
  const concat_1 = require("./concat");
21
22
  const internal_1 = require("./internal");
22
23
  const ExtRegExp_1 = require("./ExtRegExp");
@@ -29,8 +30,11 @@ __exportStar(require("./resolve"), exports);
29
30
  __exportStar(require("./concat"), exports);
30
31
  __exportStar(require("./utils"), exports);
31
32
  __exportStar(require("./ExtRegExp"), exports);
33
+ __exportStar(require("./flag-transformer"), exports);
32
34
  // Call this for certain class methods to work correctly
33
35
  (0, class_1.rgxClassInit)();
36
+ // Call this for our custom flags to work correctly
37
+ (0, flag_transformer_1.registerCustomFlagTransformers)();
34
38
  function rgxa(tokens, flags = '') {
35
39
  (0, ExtRegExp_1.assertValidRegexFlags)(flags);
36
40
  const pattern = (0, concat_1.rgxConcat)(tokens);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptolemy2002/rgx",
3
- "version": "4.4.0",
3
+ "version": "4.6.0",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",