@ptolemy2002/rgx 9.0.0 → 10.0.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/dist/concat.js CHANGED
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rgxConcat = rgxConcat;
4
+ const ExtRegExp_1 = require("./ExtRegExp");
4
5
  const internal_1 = require("./internal");
5
6
  const resolve_1 = require("./resolve");
6
7
  // Wrapper for letting an array of tokens be resolved as a concatenation instead of a union.
7
8
  function rgxConcat(tokens, groupWrap = true, currentFlags = '') {
9
+ (0, ExtRegExp_1.assertValidRegexFlags)(currentFlags);
8
10
  const result = tokens.map(t => (0, resolve_1.resolveRGXToken)(t, groupWrap, true, currentFlags)).join('');
9
11
  (0, internal_1.assureAcceptance)(tokens, currentFlags);
10
12
  return result;
@@ -1,6 +1,7 @@
1
1
  import { RGXError } from "./";
2
2
  export declare class RGXInvalidRegexStringError extends RGXError {
3
3
  got: string;
4
- constructor(message: string, got: string);
4
+ cause: SyntaxError;
5
+ constructor(message: string, got: string, cause: SyntaxError);
5
6
  calcMessage(message: string): string;
6
7
  }
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RGXInvalidRegexStringError = void 0;
4
4
  const errors_1 = require("./");
5
5
  class RGXInvalidRegexStringError extends errors_1.RGXError {
6
- constructor(message, got) {
6
+ constructor(message, got, cause) {
7
7
  super(message, 'INVALID_REGEX_STRING');
8
8
  this.name = 'RGXInvalidRegexStringError';
9
9
  this.got = got;
10
+ this.cause = cause;
10
11
  }
11
12
  calcMessage(message) {
12
- return `${message}; Got: ${JSON.stringify(this.got)}`;
13
+ return `${message}; Got: ${JSON.stringify(this.got)}; Cause: ${this.cause.message}`;
13
14
  }
14
15
  }
15
16
  exports.RGXInvalidRegexStringError = RGXInvalidRegexStringError;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,6 @@ export * from "./constants";
16
16
  export * from "./walker";
17
17
  export * from "./lexer";
18
18
  export declare function rgxa(tokens: t.RGXToken[], flags?: string): ExtRegExp;
19
- export default function rgx(flags?: string, multiline?: boolean): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => ExtRegExp;
19
+ export default function rgx(flags?: string, multiline?: boolean, verbatim?: boolean): (strings: TemplateStringsArray, ...tokens: t.RGXToken[]) => ExtRegExp;
20
20
  export declare function rgxwa<R = unknown, S = unknown, T = unknown>(source: string, tokens: RGXTokenOrPart<R, S, T>[], options?: Omit<t.RGXWOptions<R, S>, "multiline">): RGXWalker<R, S>;
21
- export declare function rgxw<R = unknown, S = unknown, T = unknown>(source: string, { multiline, ...options }?: t.RGXWOptions<R, S>): (strings: TemplateStringsArray, ...tokens: RGXTokenOrPart<R, S, T>[]) => RGXWalker<R, S>;
21
+ export declare function rgxw<R = unknown, S = unknown, T = unknown>(source: string, { multiline, verbatim, ...options }?: t.RGXWOptions<R, S>): (strings: TemplateStringsArray, ...tokens: RGXTokenOrPart<R, S, T>[]) => RGXWalker<R, S>;
package/dist/index.js CHANGED
@@ -48,18 +48,19 @@ function rgxa(tokens, flags = '') {
48
48
  const pattern = (0, concat_1.rgxConcat)(tokens, true, flags);
49
49
  return (0, ExtRegExp_1.extRegExp)(pattern, flags);
50
50
  }
51
- function rgx(flags = '', multiline = true) {
51
+ function rgx(flags = '', multiline = true, verbatim = true) {
52
52
  (0, ExtRegExp_1.assertValidRegexFlags)(flags);
53
53
  return (strings, ...tokens) => {
54
- return rgxa((0, internal_1.taggedTemplateToArray)(strings, tokens, multiline), flags);
54
+ // It is safe to assert the result because we know there will be no parts passed in here.
55
+ return rgxa((0, internal_1.rgxTaggedTemplateToArray)(strings, tokens, multiline, verbatim), flags);
55
56
  };
56
57
  }
57
58
  function rgxwa(source, tokens, options = {}) {
58
59
  (0, internal_1.assureAcceptance)(tokens.map(t => walker_1.RGXPart.check(t) ? t.token : t), '');
59
60
  return new walker_1.RGXWalker(source, tokens, options);
60
61
  }
61
- function rgxw(source, { multiline = true, ...options } = {}) {
62
+ function rgxw(source, { multiline = true, verbatim = true, ...options } = {}) {
62
63
  return (strings, ...tokens) => {
63
- return rgxwa(source, (0, internal_1.taggedTemplateToArray)(strings, tokens, multiline), options);
64
+ return rgxwa(source, (0, internal_1.rgxTaggedTemplateToArray)(strings, tokens, multiline, verbatim), options);
64
65
  };
65
66
  }
@@ -1 +1,2 @@
1
- export declare function taggedTemplateToArray<T>(strings: TemplateStringsArray, tokens: T[], multiline: boolean): (string | T)[];
1
+ import { RGXTokenOrPart } from "../walker";
2
+ export declare function rgxTaggedTemplateToArray<R = unknown, S = unknown, T = unknown>(strings: TemplateStringsArray, tokens: RGXTokenOrPart<R, S, T>[], multiline: boolean, verbatim: boolean): RGXTokenOrPart<R, S, T>[];
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.taggedTemplateToArray = taggedTemplateToArray;
4
- function taggedTemplateToArray(strings, tokens, multiline) {
3
+ exports.rgxTaggedTemplateToArray = rgxTaggedTemplateToArray;
4
+ function rgxTaggedTemplateToArray(strings, tokens, multiline, verbatim) {
5
5
  function isNullOrUndefined(value) {
6
6
  return value === null || value === undefined;
7
7
  }
@@ -12,13 +12,27 @@ function taggedTemplateToArray(strings, tokens, multiline) {
12
12
  // Strings always come before tokens
13
13
  if (!isNullOrUndefined(string)) {
14
14
  if (!multiline) {
15
- array.push(string);
15
+ if (verbatim)
16
+ array.push(string);
17
+ else
18
+ array.push({ rgxInterpolate: true, toRgx: () => string });
16
19
  }
17
20
  else {
21
+ const startsNewLine = string.startsWith("\n");
18
22
  // Remove all empty lines, remove comments, and trim whitespace from the start of each line.
19
23
  let lines = string
20
24
  .split("\n")
21
- .map(line => line.trimStart())
25
+ /*
26
+ This check makes sure
27
+ `
28
+ foo |
29
+ ${'bar'} |
30
+ baz
31
+ `
32
+
33
+ resolves to "foo | bar |baz" instead of "foo | bar|baz"
34
+ */
35
+ .map((line, i) => (i !== 0 || startsNewLine) ? line.trimStart() : line)
22
36
  // Remove comments both for the start of the line.
23
37
  .filter(line => !line.startsWith("//"))
24
38
  .filter(line => line.length > 0)
@@ -31,7 +45,10 @@ function taggedTemplateToArray(strings, tokens, multiline) {
31
45
  return line;
32
46
  })
33
47
  .join("");
34
- array.push(lines);
48
+ if (verbatim)
49
+ array.push(lines);
50
+ else
51
+ array.push({ rgxInterpolate: true, toRgx: () => lines });
35
52
  }
36
53
  }
37
54
  if (!isNullOrUndefined(token))
package/dist/resolve.js CHANGED
@@ -37,9 +37,12 @@ exports.escapeRegex = escapeRegex;
37
37
  exports.resolveRGXToken = resolveRGXToken;
38
38
  const class_1 = require("./class");
39
39
  const e = __importStar(require("./errors"));
40
+ const ExtRegExp_1 = require("./ExtRegExp");
40
41
  const tg = __importStar(require("./typeGuards"));
41
42
  function escapeRegex(value) {
42
- return value.replaceAll(/[\-\^\$.*+?^${}()|[\]\\]/g, '\\$&');
43
+ const result = value.replaceAll(/[\-\^\$.*+?^${}()|[\]\\]/g, '\\$&');
44
+ tg.assertValidRegexString(result);
45
+ return result;
43
46
  }
44
47
  function localizableVanillaRegexFlagDiff(prev, next) {
45
48
  // Remove anything other than the "ims" flags from both strings, as
@@ -56,44 +59,55 @@ function localizableVanillaRegexFlagDiff(prev, next) {
56
59
  return `${added}-${removed}`;
57
60
  }
58
61
  function resolveRGXToken(token, groupWrap = true, topLevel = true, currentFlags = '') {
59
- if (tg.isRGXNoOpToken(token))
60
- return '';
61
- if (tg.isRGXLiteralToken(token)) {
62
- const localizableFlagDiff = localizableVanillaRegexFlagDiff(currentFlags, token.flags);
63
- currentFlags = token.flags;
64
- if (!localizableFlagDiff) {
65
- if (groupWrap)
66
- return '(?:' + token.source + ')';
67
- else
68
- return token.source;
62
+ (0, ExtRegExp_1.assertValidRegexFlags)(currentFlags);
63
+ const innerResolve = () => {
64
+ if (tg.isRGXNoOpToken(token))
65
+ return '';
66
+ if (tg.isRGXLiteralToken(token)) {
67
+ const localizableFlagDiff = localizableVanillaRegexFlagDiff(currentFlags, token.flags);
68
+ currentFlags = token.flags;
69
+ if (!localizableFlagDiff) {
70
+ if (groupWrap)
71
+ return '(?:' + token.source + ')';
72
+ else
73
+ return token.source;
74
+ }
75
+ else {
76
+ return `(?${localizableFlagDiff}:${token.source})`;
77
+ }
69
78
  }
70
- else {
71
- return `(?${localizableFlagDiff}:${token.source})`;
79
+ if (tg.isRGXNativeToken(token))
80
+ return escapeRegex(String(token));
81
+ if (tg.isRGXConvertibleToken(token)) {
82
+ // If it's an interpolation, we want to just return it as-is.
83
+ // This will mean the result might be an invalid regex string,
84
+ // but that's why we have a check.
85
+ if (token.rgxInterpolate)
86
+ return String(token.toRgx());
87
+ // The top-level group-wrapping preference propogates to a direct convertible token, but after that
88
+ // the preference falls back to true whenever a token doesn't explicitly specify a preference.
89
+ return resolveRGXToken(token.toRgx(), token.rgxGroupWrap ?? (topLevel ? groupWrap : true), false, currentFlags);
72
90
  }
73
- }
74
- if (tg.isRGXNativeToken(token))
75
- return escapeRegex(String(token));
76
- if (tg.isRGXConvertibleToken(token)) {
77
- // The top-level group-wrapping preference propogates to a direct convertible token, but after that
78
- // the preference falls back to true whenever a token doesn't explicitly specify a preference.
79
- return resolveRGXToken(token.toRgx(), token.rgxGroupWrap ?? (topLevel ? groupWrap : true), false, currentFlags);
80
- }
81
- // Interpret arrays as unions
82
- if (tg.isRGXArrayToken(token, false)) {
83
- if (token.length === 0)
84
- return '';
85
- if (token.length > 1) {
86
- // Remove duplicates
87
- token = [...(0, class_1.removeRgxUnionDuplicates)(...token)];
88
- // Don't preserve group wrapping preference for the recursive calls
89
- if (groupWrap)
90
- return '(?:' + token.map(t => resolveRGXToken(t, true, false, currentFlags)).join('|') + ')';
91
- else
92
- return token.map(t => resolveRGXToken(t, true, false, currentFlags)).join('|');
91
+ // Interpret arrays as unions
92
+ if (tg.isRGXArrayToken(token, false)) {
93
+ if (token.length === 0)
94
+ return '';
95
+ if (token.length > 1) {
96
+ // Remove duplicates
97
+ token = [...(0, class_1.removeRgxUnionDuplicates)(...token)];
98
+ // Don't preserve group wrapping preference for the recursive calls
99
+ if (groupWrap)
100
+ return '(?:' + token.map(t => resolveRGXToken(t, true, false, currentFlags)).join('|') + ')';
101
+ else
102
+ return token.map(t => resolveRGXToken(t, true, false, currentFlags)).join('|');
103
+ }
104
+ return resolveRGXToken(token[0], true, false, currentFlags);
93
105
  }
94
- return resolveRGXToken(token[0], true, false, currentFlags);
95
- }
96
- // Ignoring this line since it should be impossible to reach if the types are correct, but we need it to satisfy the return type
97
- /* istanbul ignore next */
98
- throw new e.RGXInvalidTokenError(`Invalid RGX token: ${token}`, null, token);
106
+ // Ignoring this line since it should be impossible to reach if the types are correct, but we need it to satisfy the return type
107
+ /* istanbul ignore next */
108
+ throw new e.RGXInvalidTokenError(`Invalid RGX token: ${token}`, null, token);
109
+ };
110
+ const result = innerResolve();
111
+ tg.assertValidRegexString(result);
112
+ return result;
99
113
  }
@@ -93,13 +93,15 @@ function assertRGXNativeToken(value) {
93
93
  }
94
94
  function isRGXConvertibleToken(value, returnCheck = true) {
95
95
  if (typeof value === 'object' && value !== null && 'toRgx' in value) {
96
- // The rgxGroupWrap, rgxIsRepeatable, and rgxIsGroup properties are optional, but if they exist they must be booleans.
96
+ // The rgxGroupWrap, interpolate, rgxIsRepeatable, and rgxIsGroup properties are optional, but if they exist they must be booleans.
97
97
  if ('rgxGroupWrap' in value && typeof value.rgxGroupWrap !== 'boolean')
98
98
  return false;
99
99
  if ('rgxIsRepeatable' in value && typeof value.rgxIsRepeatable !== 'boolean')
100
100
  return false;
101
101
  if ('rgxIsGroup' in value && typeof value.rgxIsGroup !== 'boolean')
102
102
  return false;
103
+ if ('rgxInterpolate' in value && typeof value.rgxInterpolate !== 'boolean')
104
+ return false;
103
105
  // If the rgxAcceptInsertion property exists, it must be a function that returns a string or boolean.
104
106
  if ('rgxAcceptInsertion' in value) {
105
107
  if (!(0, is_callable_1.default)(value.rgxAcceptInsertion))
@@ -240,13 +242,30 @@ function isValidRegexString(value) {
240
242
  new RegExp(value);
241
243
  return true;
242
244
  }
243
- catch {
244
- return false;
245
+ catch (e) {
246
+ if (e instanceof SyntaxError) {
247
+ return false;
248
+ }
249
+ // This is ignored because I don't know what king of
250
+ // unexpected errors might happen.
251
+ /* istanbul ignore next */
252
+ throw e;
245
253
  }
246
254
  }
247
255
  function assertValidRegexString(value) {
248
256
  if (!isValidRegexString(value)) {
249
- throw new e.RGXInvalidRegexStringError("Invalid regex string", value);
257
+ try {
258
+ new RegExp(value);
259
+ }
260
+ catch (err) {
261
+ if (err instanceof SyntaxError) {
262
+ throw new e.RGXInvalidRegexStringError("Invalid regex string", value, err);
263
+ }
264
+ // This is ignored because I don't know what king of
265
+ // unexpected errors might happen.
266
+ /* istanbul ignore next */
267
+ throw err;
268
+ }
250
269
  }
251
270
  }
252
271
  function isValidVanillaRegexFlags(value) {
package/dist/types.d.ts CHANGED
@@ -12,6 +12,7 @@ export type RGXConvertibleToken = {
12
12
  readonly rgxGroupWrap?: boolean;
13
13
  readonly rgxIsGroup?: boolean;
14
14
  readonly rgxIsRepeatable?: boolean;
15
+ readonly rgxInterpolate?: boolean;
15
16
  };
16
17
  export type RGXToken = RGXNativeToken | RGXLiteralToken | RGXConvertibleToken | RGXToken[];
17
18
  export type RGXClassTokenConstructor = new (...args: unknown[]) => RGXClassToken;
@@ -49,6 +50,8 @@ export type ValidRegexFlags = Branded<string, [ValidRegexFlagsBrandSymbol]> | Va
49
50
  export declare const validIdentifierSymbol: unique symbol;
50
51
  export type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
51
52
  export type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
52
- export type RGXWOptions<R = unknown, S = unknown> = RGXWalkerOptions<R, S> & {
53
+ export type RGXOptions = {
53
54
  multiline?: boolean;
55
+ verbatim?: boolean;
54
56
  };
57
+ export type RGXWOptions<R = unknown, S = unknown> = RGXWalkerOptions<R, S> & RGXOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptolemy2002/rgx",
3
- "version": "9.0.0",
3
+ "version": "10.0.0",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",