@ptolemy2002/rgx 9.0.0 → 11.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/README.md +1 -0
- package/dist/ExtRegExp.d.ts +1 -1
- package/dist/ExtRegExp.js +23 -2
- package/dist/class/group.js +1 -1
- package/dist/class/lookahead.js +1 -1
- package/dist/class/lookbehind.js +1 -1
- package/dist/class/repeat.js +1 -1
- package/dist/class/subpattern.js +2 -2
- package/dist/collection.js +1 -1
- package/dist/concat.js +2 -0
- package/dist/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/errors/invalidRegexString.d.ts +2 -1
- package/dist/errors/invalidRegexString.js +3 -2
- package/dist/errors/notDirectRegexp.d.ts +6 -0
- package/dist/errors/notDirectRegexp.js +15 -0
- package/dist/flag-transformer/accentInsensitive.js +3 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -6
- package/dist/internal/taggedTemplateToArray.d.ts +2 -1
- package/dist/internal/taggedTemplateToArray.js +22 -5
- package/dist/lexer/base.js +2 -2
- package/dist/resolve.js +52 -38
- package/dist/typeGuards.js +28 -4
- package/dist/types.d.ts +4 -1
- package/dist/utils/createRegex.d.ts +4 -0
- package/dist/utils/createRegex.js +25 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/regexWithFlags.js +3 -5
- package/dist/walker/base.d.ts +2 -2
- package/dist/walker/base.js +8 -7
- package/dist/walker/part.d.ts +10 -6
- package/dist/walker/part.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ Because there is so much to document, it has been broken up into multiple files.
|
|
|
17
17
|
- [escapeRegex](./docs/util/escapeRegex.md) - The `escapeRegex` function, which escapes special regex characters in a given string and assures you that the result is valid Regex.
|
|
18
18
|
- [regexMatchAtPosition](./docs/util/regexMatchAtPosition.md) - The `regexMatchAtPosition` function and related functions, which attempt to match a given regular expression at a specific position in a string.
|
|
19
19
|
- [regexWithFlags](./docs/util/regexWithFlags.md) - The `regexWithFlags` function, which creates a new regular expression with the same source as a given regular expression but with different flags.
|
|
20
|
+
- [createRegex](./docs/util/createRegex.md) - The `createRegex` function, which safely constructs a `RegExp` or `ExtRegExp` from a pattern string, converting `SyntaxError` into `RGXInvalidRegexStringError`.
|
|
20
21
|
- [createRGXClassGuardFunction](./docs/util/createRGXClassGuardFunction.md) - The `createRGXClassGuardFunction` and `createAssertRGXClassGuardFunction` utilities for creating type guard and assertion functions for class instances.
|
|
21
22
|
- `class` - A directory containing documentation for all classes in the library.
|
|
22
23
|
- [collection](./docs/class/collection.md) - The `RGXTokenCollection` class, which is a collection of tokens.
|
package/dist/ExtRegExp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ValidRegexFlags } from "./types";
|
|
2
|
-
export type RegExpFlagTransformer = (exp: RegExp) =>
|
|
2
|
+
export type RegExpFlagTransformer = (exp: RegExp) => [string, string];
|
|
3
3
|
export declare class ExtRegExp extends RegExp {
|
|
4
4
|
private extFlags;
|
|
5
5
|
constructor(pattern: string | RegExp, flags?: string);
|
package/dist/ExtRegExp.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.assertValidRegexFlags = assertValidRegexFlags;
|
|
|
12
12
|
const errors_1 = require("./errors");
|
|
13
13
|
const internal_1 = require("./internal");
|
|
14
14
|
const typeGuards_1 = require("./typeGuards");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
15
16
|
const flagTransformers = {};
|
|
16
17
|
class ExtRegExp extends RegExp {
|
|
17
18
|
constructor(pattern, flags = '') {
|
|
@@ -20,7 +21,7 @@ class ExtRegExp extends RegExp {
|
|
|
20
21
|
const customFlags = extractCustomRegexFlags(flags);
|
|
21
22
|
const source = pattern instanceof RegExp ? pattern.source : pattern;
|
|
22
23
|
const alreadyAppliedFlags = pattern instanceof RegExp ? pattern.flags : '';
|
|
23
|
-
const { source: transformedSource, flags: transformedFlags } = applyFlagTransformers(
|
|
24
|
+
const { source: transformedSource, flags: transformedFlags } = applyFlagTransformers((0, utils_1.createRegex)(source, vanillaFlags), customFlags, alreadyAppliedFlags);
|
|
24
25
|
super(transformedSource, transformedFlags);
|
|
25
26
|
this.extFlags = customFlags;
|
|
26
27
|
}
|
|
@@ -56,9 +57,29 @@ function unregisterFlagTransformer(key) {
|
|
|
56
57
|
delete flagTransformers[key];
|
|
57
58
|
}
|
|
58
59
|
function applyFlagTransformers(regex, flags, alreadyAppliedFlags = '') {
|
|
60
|
+
if (Object.getPrototypeOf(regex) !== RegExp.prototype) {
|
|
61
|
+
throw new errors_1.RGXNotDirectRegExpError("Cannot apply flag transformers to non-direct RegExp instances", regex.constructor.name);
|
|
62
|
+
}
|
|
59
63
|
for (const flag in flagTransformers) {
|
|
60
64
|
if (flags.includes(flag) && !alreadyAppliedFlags.includes(flag)) {
|
|
61
|
-
|
|
65
|
+
const [newSource, newFlags] = flagTransformers[flag](regex);
|
|
66
|
+
try {
|
|
67
|
+
if ((0, typeGuards_1.isValidVanillaRegexFlags)(newFlags)) {
|
|
68
|
+
regex = new RegExp(newSource, newFlags);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
throw new errors_1.RGXInvalidVanillaRegexFlagsError(`Flag transformer for flag "${flag}" produced invalid vanilla regex flags.`, newFlags);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
if (e instanceof SyntaxError) {
|
|
76
|
+
throw new errors_1.RGXInvalidRegexStringError(`Flag transformer for flag "${flag}" produced an invalid regex.`, newSource, e);
|
|
77
|
+
}
|
|
78
|
+
// This is ignored because I don't know what kind of
|
|
79
|
+
// unexpected errors might happen.
|
|
80
|
+
/* istanbul ignore next */
|
|
81
|
+
throw e;
|
|
82
|
+
}
|
|
62
83
|
alreadyAppliedFlags += flag;
|
|
63
84
|
}
|
|
64
85
|
}
|
package/dist/class/group.js
CHANGED
package/dist/class/lookahead.js
CHANGED
package/dist/class/lookbehind.js
CHANGED
package/dist/class/repeat.js
CHANGED
|
@@ -90,7 +90,7 @@ class RGXRepeatToken extends base_1.RGXClassToken {
|
|
|
90
90
|
if (this.min === 0 && this.max === 0)
|
|
91
91
|
return null;
|
|
92
92
|
const resolvedSource = (0, resolve_1.resolveRGXToken)(this.token);
|
|
93
|
-
return
|
|
93
|
+
return (0, utils_1.createRegex)(`${resolvedSource}${this.repeaterSuffix}`);
|
|
94
94
|
}
|
|
95
95
|
clone(depth = "max") {
|
|
96
96
|
if (depth === 0)
|
package/dist/class/subpattern.js
CHANGED
|
@@ -26,10 +26,10 @@ class RGXSubpatternToken extends base_1.RGXClassToken {
|
|
|
26
26
|
}
|
|
27
27
|
toRgx() {
|
|
28
28
|
if (typeof this.pattern === "string") {
|
|
29
|
-
return
|
|
29
|
+
return (0, utils_1.createRegex)(`\\k<${this.pattern}>`);
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
return
|
|
32
|
+
return (0, utils_1.createRegex)(`\\${this.pattern}`);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
clone(depth = "max") {
|
package/dist/collection.js
CHANGED
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;
|
package/dist/errors/base.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'CONSTANT_CONFLICT' | 'INVALID_CONSTANT_KEY' | 'INSERTION_REJECTED' | 'REGEX_NOT_MATCHED_AT_POSITION' | 'PART_VALIDATION_FAILED' | 'INVALID_LEXER_MODE' | 'LEXEME_NOT_MATCHED_AT_POSITION' | 'INVALID_RGX_LEXER' | 'INVALID_RGX_WALKER' | 'INVALID_RGX_PART';
|
|
1
|
+
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'CONSTANT_CONFLICT' | 'INVALID_CONSTANT_KEY' | 'INSERTION_REJECTED' | 'REGEX_NOT_MATCHED_AT_POSITION' | 'PART_VALIDATION_FAILED' | 'INVALID_LEXER_MODE' | 'LEXEME_NOT_MATCHED_AT_POSITION' | 'INVALID_RGX_LEXER' | 'INVALID_RGX_WALKER' | 'INVALID_RGX_PART' | 'NOT_DIRECT_REGEXP';
|
|
2
2
|
export declare class RGXError extends Error {
|
|
3
3
|
_message: string;
|
|
4
4
|
code: RGXErrorCode;
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -35,3 +35,4 @@ __exportStar(require("./lexemeNotMatchedAtPosition"), exports);
|
|
|
35
35
|
__exportStar(require("./invalidLexer"), exports);
|
|
36
36
|
__exportStar(require("./invalidWalker"), exports);
|
|
37
37
|
__exportStar(require("./invalidPart"), exports);
|
|
38
|
+
__exportStar(require("./notDirectRegexp"), exports);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RGXError } from "./";
|
|
2
2
|
export declare class RGXInvalidRegexStringError extends RGXError {
|
|
3
3
|
got: string;
|
|
4
|
-
|
|
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;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXNotDirectRegExpError = void 0;
|
|
4
|
+
const base_1 = require("./base");
|
|
5
|
+
class RGXNotDirectRegExpError extends base_1.RGXError {
|
|
6
|
+
constructor(message, gotConstructorName) {
|
|
7
|
+
super(message, 'NOT_DIRECT_REGEXP');
|
|
8
|
+
this.name = 'RGXNotDirectRegExpError';
|
|
9
|
+
this.gotConstructorName = gotConstructorName;
|
|
10
|
+
}
|
|
11
|
+
calcMessage(message) {
|
|
12
|
+
return `${message}; Expected direct instance of RegExp; Got instance of ${this.gotConstructorName}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.RGXNotDirectRegExpError = RGXNotDirectRegExpError;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.accentInsensitiveFlagTransformer = void 0;
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
5
|
const resolve_1 = require("../resolve");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
6
7
|
const accentPatterns = [
|
|
7
8
|
"(a|á|à|ä|â|ã)", "(A|Á|À|Ä|Â|Ã)",
|
|
8
9
|
"(e|é|è|ë|ê)", "(E|É|È|Ë|Ê)",
|
|
@@ -26,8 +27,8 @@ const accentInsensitiveFlagTransformer = function (exp) {
|
|
|
26
27
|
const flags = exp.flags;
|
|
27
28
|
accentPatterns.forEach((pattern) => {
|
|
28
29
|
// Replace any of the characters in the pattern with the pattern itself
|
|
29
|
-
source = source.replaceAll(
|
|
30
|
+
source = source.replaceAll((0, utils_1.createRegex)(nonEscapeBound + nonLocalizedFlagBound + nonCharacterClassBound + pattern, "g"), pattern);
|
|
30
31
|
});
|
|
31
|
-
return
|
|
32
|
+
return [source, flags];
|
|
32
33
|
};
|
|
33
34
|
exports.accentInsensitiveFlagTransformer = accentInsensitiveFlagTransformer;
|
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
|
@@ -24,6 +24,7 @@ const concat_1 = require("./concat");
|
|
|
24
24
|
const internal_1 = require("./internal");
|
|
25
25
|
const ExtRegExp_1 = require("./ExtRegExp");
|
|
26
26
|
const walker_1 = require("./walker");
|
|
27
|
+
const utils_1 = require("./utils");
|
|
27
28
|
__exportStar(require("./errors"), exports);
|
|
28
29
|
__exportStar(require("./types"), exports);
|
|
29
30
|
__exportStar(require("./typeGuards"), exports);
|
|
@@ -46,20 +47,20 @@ function rgxa(tokens, flags = '') {
|
|
|
46
47
|
(0, ExtRegExp_1.assertValidRegexFlags)(flags);
|
|
47
48
|
(0, internal_1.assureAcceptance)(tokens, flags);
|
|
48
49
|
const pattern = (0, concat_1.rgxConcat)(tokens, true, flags);
|
|
49
|
-
return (0,
|
|
50
|
+
return (0, utils_1.createRegex)(pattern, flags, true);
|
|
50
51
|
}
|
|
51
|
-
function rgx(flags = '', multiline = true) {
|
|
52
|
-
(0, ExtRegExp_1.assertValidRegexFlags)(flags);
|
|
52
|
+
function rgx(flags = '', multiline = true, verbatim = true) {
|
|
53
53
|
return (strings, ...tokens) => {
|
|
54
|
-
|
|
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.
|
|
64
|
+
return rgxwa(source, (0, internal_1.rgxTaggedTemplateToArray)(strings, tokens, multiline, verbatim), options);
|
|
64
65
|
};
|
|
65
66
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
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.
|
|
4
|
-
function
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/lexer/base.js
CHANGED
|
@@ -44,7 +44,7 @@ class RGXLexer {
|
|
|
44
44
|
let dataPart = {};
|
|
45
45
|
if (lexemeDefinition.type === "resolve") {
|
|
46
46
|
const { token } = lexemeDefinition;
|
|
47
|
-
const regex =
|
|
47
|
+
const regex = (0, utils_1.createRegex)((0, resolve_1.resolveRGXToken)(token));
|
|
48
48
|
// Since the assertion will throw an error if there is no match, this is safe.
|
|
49
49
|
const match = (0, utils_1.assertRegexMatchesAtPosition)(regex, this.source, startPosition, 10, true);
|
|
50
50
|
raw = match[0];
|
|
@@ -159,7 +159,7 @@ class RGXLexer {
|
|
|
159
159
|
skipWhitespace() {
|
|
160
160
|
if (this.isAtEnd())
|
|
161
161
|
return;
|
|
162
|
-
const regex =
|
|
162
|
+
const regex = (0, utils_1.createRegex)((0, resolve_1.resolveRGXToken)((0, constants_1.rgxConstant)("whitespace-block")));
|
|
163
163
|
const match = (0, utils_1.regexMatchAtPosition)(regex, this.source, this.position, true);
|
|
164
164
|
if (match !== null) {
|
|
165
165
|
this.position += match[0].length;
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
return
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
}
|
package/dist/typeGuards.js
CHANGED
|
@@ -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))
|
|
@@ -219,6 +221,11 @@ function isRGXToken(value, type = null, matchLength = true) {
|
|
|
219
221
|
function assertRGXToken(value, type = null, matchLength = true) {
|
|
220
222
|
if (!isRGXToken(value, type, matchLength)) {
|
|
221
223
|
const flatType = rgxTokenTypeGuardInputToFlat(type);
|
|
224
|
+
/*
|
|
225
|
+
ts-ignore
|
|
226
|
+
This line sometimes throws a weird error in VSCode, but it doesn't prevent a build, and I don't know how to fix it.
|
|
227
|
+
It's an excessively deep type error on the `value` variable, which is typed as `unknown`.
|
|
228
|
+
*/
|
|
222
229
|
throw new e.RGXInvalidTokenError("Invalid RGX token", flatType === null ? null : { type: "tokenType", values: [flatType] }, value);
|
|
223
230
|
}
|
|
224
231
|
}
|
|
@@ -240,13 +247,30 @@ function isValidRegexString(value) {
|
|
|
240
247
|
new RegExp(value);
|
|
241
248
|
return true;
|
|
242
249
|
}
|
|
243
|
-
catch {
|
|
244
|
-
|
|
250
|
+
catch (e) {
|
|
251
|
+
if (e instanceof SyntaxError) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
// This is ignored because I don't know what kind of
|
|
255
|
+
// unexpected errors might happen.
|
|
256
|
+
/* istanbul ignore next */
|
|
257
|
+
throw e;
|
|
245
258
|
}
|
|
246
259
|
}
|
|
247
260
|
function assertValidRegexString(value) {
|
|
248
261
|
if (!isValidRegexString(value)) {
|
|
249
|
-
|
|
262
|
+
try {
|
|
263
|
+
new RegExp(value);
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
if (err instanceof SyntaxError) {
|
|
267
|
+
throw new e.RGXInvalidRegexStringError("Invalid regex string", value, err);
|
|
268
|
+
}
|
|
269
|
+
// This is ignored because I don't know what king of
|
|
270
|
+
// unexpected errors might happen.
|
|
271
|
+
/* istanbul ignore next */
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
250
274
|
}
|
|
251
275
|
}
|
|
252
276
|
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
|
|
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;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ExtRegExp } from "../ExtRegExp";
|
|
2
|
+
export declare function createRegex(pattern: string, flags?: string): RegExp;
|
|
3
|
+
export declare function createRegex(pattern: string, flags: string, extended: false): RegExp;
|
|
4
|
+
export declare function createRegex(pattern: string, flags: string, extended: true): ExtRegExp;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRegex = createRegex;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const ExtRegExp_1 = require("../ExtRegExp");
|
|
6
|
+
const typeGuards_1 = require("../typeGuards");
|
|
7
|
+
function createRegex(pattern, flags = "", extended = false) {
|
|
8
|
+
// ExtRegExp will handle validation of flags if extended is true, otherwise we validate them here
|
|
9
|
+
if (!extended)
|
|
10
|
+
(0, typeGuards_1.assertValidVanillaRegexFlags)(flags);
|
|
11
|
+
try {
|
|
12
|
+
if (extended)
|
|
13
|
+
return new ExtRegExp_1.ExtRegExp(pattern, flags);
|
|
14
|
+
else
|
|
15
|
+
return new RegExp(pattern, flags);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
if (e instanceof SyntaxError) {
|
|
19
|
+
throw new errors_1.RGXInvalidRegexStringError("Invalid regex string", pattern, e);
|
|
20
|
+
}
|
|
21
|
+
// The invalid flags error thrown by ExtRegExp
|
|
22
|
+
// will be rethrown here.
|
|
23
|
+
throw e;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -18,3 +18,4 @@ __exportStar(require("./regexMatchAtPosition"), exports);
|
|
|
18
18
|
__exportStar(require("./regexWithFlags"), exports);
|
|
19
19
|
__exportStar(require("./normalizeRegexFlags"), exports);
|
|
20
20
|
__exportStar(require("./createRGXClassGuardFunction"), exports);
|
|
21
|
+
__exportStar(require("./createRegex"), exports);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.regexWithFlags = regexWithFlags;
|
|
4
|
-
const ExtRegExp_1 = require("../ExtRegExp");
|
|
5
4
|
const normalizeRegexFlags_1 = require("./normalizeRegexFlags");
|
|
6
|
-
const
|
|
5
|
+
const createRegex_1 = require("./createRegex");
|
|
7
6
|
function regexWithFlags(exp, flags, replace = false) {
|
|
8
|
-
(0, ExtRegExp_1.assertValidRegexFlags)(flags);
|
|
9
7
|
if (replace)
|
|
10
|
-
return
|
|
8
|
+
return (0, createRegex_1.createRegex)(exp.source, flags, true);
|
|
11
9
|
const existingFlags = exp.flags;
|
|
12
10
|
const newFlags = existingFlags + flags;
|
|
13
|
-
return
|
|
11
|
+
return (0, createRegex_1.createRegex)(exp.source, (0, normalizeRegexFlags_1.normalizeRegexFlags)(newFlags), true);
|
|
14
12
|
}
|
package/dist/walker/base.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare class RGXWalker<R, S = unknown> {
|
|
|
31
31
|
constructor(source: string, tokens: RGXTokenOrPart<R, S>[], options?: RGXWalkerOptions<R, S>);
|
|
32
32
|
stop(): this;
|
|
33
33
|
atTokenEnd(): boolean;
|
|
34
|
-
hasNextToken(predicate?: (token: RGXToken | RGXPart<R, S>) => boolean): boolean;
|
|
34
|
+
hasNextToken(predicate?: (token: RGXToken | RGXPart<R, S, unknown>) => boolean): boolean;
|
|
35
35
|
atSourceEnd(): boolean;
|
|
36
36
|
hasNextSource(predicate?: (rest: string) => boolean): boolean;
|
|
37
37
|
lastCapture(): RGXCapture | null;
|
|
@@ -42,7 +42,7 @@ export declare class RGXWalker<R, S = unknown> {
|
|
|
42
42
|
step(): RGXCapture | null;
|
|
43
43
|
stepToToken(predicate: (token: RGXTokenOrPart<R>) => boolean): this;
|
|
44
44
|
stepToPart(predicate?: (part: RGXPart<R, S, unknown>) => boolean): this;
|
|
45
|
-
walk():
|
|
45
|
+
walk(): R;
|
|
46
46
|
clone(depth?: CloneDepth): RGXWalker<R, S>;
|
|
47
47
|
}
|
|
48
48
|
export declare function rgxWalker<R, S = unknown>(...args: ConstructorParameters<typeof RGXWalker<R, S>>): RGXWalker<R, S>;
|
package/dist/walker/base.js
CHANGED
|
@@ -88,7 +88,7 @@ class RGXWalker {
|
|
|
88
88
|
return this.source.slice(this.sourcePosition);
|
|
89
89
|
}
|
|
90
90
|
capture(token, includeMatch = false) {
|
|
91
|
-
const regex =
|
|
91
|
+
const regex = (0, utils_1.createRegex)((0, resolve_1.resolveRGXToken)(part_1.RGXPart.check(token) ? token.token : token));
|
|
92
92
|
const match = (0, utils_1.assertRegexMatchesAtPosition)(regex, this.source, this.sourcePosition, 10, true);
|
|
93
93
|
this.sourcePosition += match[0].length;
|
|
94
94
|
return includeMatch ? match : match[0];
|
|
@@ -108,7 +108,7 @@ class RGXWalker {
|
|
|
108
108
|
let silent = false;
|
|
109
109
|
// Ask Part what to do — control flow via return values, not flags.
|
|
110
110
|
if (isPart) {
|
|
111
|
-
const control = token.beforeCapture?.(
|
|
111
|
+
const control = token.beforeCapture?.({ part: token, walker: this });
|
|
112
112
|
if (control === "stop") {
|
|
113
113
|
this._stopped = true;
|
|
114
114
|
return null;
|
|
@@ -134,7 +134,7 @@ class RGXWalker {
|
|
|
134
134
|
}
|
|
135
135
|
catch (e) {
|
|
136
136
|
if (isPart && e instanceof errors_1.RGXRegexNotMatchedAtPositionError) {
|
|
137
|
-
token.afterFailure?.(e,
|
|
137
|
+
token.afterFailure?.(e, { part: token, walker: this });
|
|
138
138
|
}
|
|
139
139
|
throw e;
|
|
140
140
|
}
|
|
@@ -159,11 +159,11 @@ class RGXWalker {
|
|
|
159
159
|
// Validate the part. If validation fails, it will throw an error, so nothing below will run.
|
|
160
160
|
if (isPart) {
|
|
161
161
|
try {
|
|
162
|
-
token.validate(captureResult,
|
|
162
|
+
token.validate(captureResult, { part: token, walker: this });
|
|
163
163
|
}
|
|
164
164
|
catch (e) {
|
|
165
165
|
if (e instanceof errors_1.RGXPartValidationFailedError) {
|
|
166
|
-
token.afterValidationFailure?.(e,
|
|
166
|
+
token.afterValidationFailure?.(e, { part: token, walker: this });
|
|
167
167
|
}
|
|
168
168
|
throw e;
|
|
169
169
|
}
|
|
@@ -179,7 +179,7 @@ class RGXWalker {
|
|
|
179
179
|
}
|
|
180
180
|
// Notify Part after capture
|
|
181
181
|
if (isPart) {
|
|
182
|
-
token.afterCapture?.(captureResult,
|
|
182
|
+
token.afterCapture?.(captureResult, { part: token, walker: this });
|
|
183
183
|
}
|
|
184
184
|
if (!this.infinite || this.tokenPosition < this.tokens.length - 1) {
|
|
185
185
|
this.tokenPosition++;
|
|
@@ -213,7 +213,8 @@ class RGXWalker {
|
|
|
213
213
|
return this;
|
|
214
214
|
}
|
|
215
215
|
walk() {
|
|
216
|
-
|
|
216
|
+
this.stepToToken(() => false);
|
|
217
|
+
return this.reduced;
|
|
217
218
|
}
|
|
218
219
|
// Clone method
|
|
219
220
|
clone(depth = "max") {
|
package/dist/walker/part.d.ts
CHANGED
|
@@ -12,15 +12,19 @@ export type RGXCapture<T = unknown> = {
|
|
|
12
12
|
branch: number;
|
|
13
13
|
groups: Record<string, string> | null;
|
|
14
14
|
};
|
|
15
|
+
export type RGXPartContext<R, S = unknown, T = string> = {
|
|
16
|
+
part: RGXPart<R, S, T>;
|
|
17
|
+
walker: RGXWalker<R, S>;
|
|
18
|
+
};
|
|
15
19
|
export type RGXPartOptions<R, S = unknown, T = string> = {
|
|
16
20
|
id: string;
|
|
17
21
|
rawTransform: (captured: string) => string;
|
|
18
22
|
transform: (captured: string) => T;
|
|
19
|
-
validate: (captured: RGXCapture<T>,
|
|
20
|
-
beforeCapture: ((
|
|
21
|
-
afterCapture: ((capture: RGXCapture<T>,
|
|
22
|
-
afterFailure: ((e: RGXRegexNotMatchedAtPositionError,
|
|
23
|
-
afterValidationFailure: ((e: RGXPartValidationFailedError,
|
|
23
|
+
validate: (captured: RGXCapture<T>, context: RGXPartContext<R, S, T>) => boolean | string;
|
|
24
|
+
beforeCapture: ((context: RGXPartContext<R, S, T>) => RGXPartControl) | null;
|
|
25
|
+
afterCapture: ((capture: RGXCapture<T>, context: RGXPartContext<R, S, T>) => void) | null;
|
|
26
|
+
afterFailure: ((e: RGXRegexNotMatchedAtPositionError, context: RGXPartContext<R, S, T>) => void) | null;
|
|
27
|
+
afterValidationFailure: ((e: RGXPartValidationFailedError, context: RGXPartContext<R, S, T>) => void) | null;
|
|
24
28
|
};
|
|
25
29
|
export declare class RGXPart<R, S = unknown, T = string> {
|
|
26
30
|
id: string | null;
|
|
@@ -38,7 +42,7 @@ export declare class RGXPart<R, S = unknown, T = string> {
|
|
|
38
42
|
hasId(): this is RGXPart<R, S, T> & {
|
|
39
43
|
id: string;
|
|
40
44
|
};
|
|
41
|
-
validate(capture: RGXCapture<T>,
|
|
45
|
+
validate(capture: RGXCapture<T>, context: RGXPartContext<R, S, T>): void;
|
|
42
46
|
clone(depth?: CloneDepth): RGXPart<R, S, T>;
|
|
43
47
|
}
|
|
44
48
|
export declare function rgxPart<R, S = unknown, T = string>(...args: ConstructorParameters<typeof RGXPart<R, S, T>>): RGXPart<R, S, T>;
|
package/dist/walker/part.js
CHANGED
|
@@ -21,8 +21,8 @@ class RGXPart {
|
|
|
21
21
|
hasId() {
|
|
22
22
|
return this.id !== null;
|
|
23
23
|
}
|
|
24
|
-
validate(capture,
|
|
25
|
-
const result = this._validate(capture,
|
|
24
|
+
validate(capture, context) {
|
|
25
|
+
const result = this._validate(capture, context);
|
|
26
26
|
if (result === true)
|
|
27
27
|
return;
|
|
28
28
|
const message = typeof result === "string" ? result : "Part Validation Failed";
|