@ptolemy2002/rgx 10.0.0 → 11.1.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/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- 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.js +2 -2
- package/dist/lexer/base.js +2 -2
- package/dist/typeGuards.js +6 -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 +28 -8
- 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/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);
|
|
@@ -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.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,10 +47,9 @@ 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
52
|
function rgx(flags = '', multiline = true, verbatim = true) {
|
|
52
|
-
(0, ExtRegExp_1.assertValidRegexFlags)(flags);
|
|
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
55
|
return rgxa((0, internal_1.rgxTaggedTemplateToArray)(strings, tokens, multiline, verbatim), flags);
|
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/typeGuards.js
CHANGED
|
@@ -221,6 +221,11 @@ function isRGXToken(value, type = null, matchLength = true) {
|
|
|
221
221
|
function assertRGXToken(value, type = null, matchLength = true) {
|
|
222
222
|
if (!isRGXToken(value, type, matchLength)) {
|
|
223
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
|
+
*/
|
|
224
229
|
throw new e.RGXInvalidTokenError("Invalid RGX token", flatType === null ? null : { type: "tokenType", values: [flatType] }, value);
|
|
225
230
|
}
|
|
226
231
|
}
|
|
@@ -246,7 +251,7 @@ function isValidRegexString(value) {
|
|
|
246
251
|
if (e instanceof SyntaxError) {
|
|
247
252
|
return false;
|
|
248
253
|
}
|
|
249
|
-
// This is ignored because I don't know what
|
|
254
|
+
// This is ignored because I don't know what kind of
|
|
250
255
|
// unexpected errors might happen.
|
|
251
256
|
/* istanbul ignore next */
|
|
252
257
|
throw e;
|
|
@@ -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,16 @@ class RGXWalker {
|
|
|
134
134
|
}
|
|
135
135
|
catch (e) {
|
|
136
136
|
if (isPart && e instanceof errors_1.RGXRegexNotMatchedAtPositionError) {
|
|
137
|
-
token.afterFailure?.(e,
|
|
137
|
+
const control = token.afterFailure?.(e, { part: token, walker: this });
|
|
138
|
+
if (control === "stop") {
|
|
139
|
+
this._stopped = true;
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
if (control === "skip") {
|
|
143
|
+
this.tokenPosition++;
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
// Handling silent is pointless here since it won't add a capture in either case, so we don't check for it.
|
|
138
147
|
}
|
|
139
148
|
throw e;
|
|
140
149
|
}
|
|
@@ -144,7 +153,7 @@ class RGXWalker {
|
|
|
144
153
|
let branch = 0;
|
|
145
154
|
// Determine branch index for captureResult by finding the first index
|
|
146
155
|
// with non-undefined match group.
|
|
147
|
-
for (let i = 0; i < capture.length; i++) {
|
|
156
|
+
for (let i = 0; i < capture.length - 1; i++) {
|
|
148
157
|
const branchKey = `rgx_branch_${i}`;
|
|
149
158
|
if (capture.groups && capture.groups[branchKey] !== undefined) {
|
|
150
159
|
branch = i;
|
|
@@ -159,11 +168,21 @@ class RGXWalker {
|
|
|
159
168
|
// Validate the part. If validation fails, it will throw an error, so nothing below will run.
|
|
160
169
|
if (isPart) {
|
|
161
170
|
try {
|
|
162
|
-
token.validate(captureResult,
|
|
171
|
+
token.validate(captureResult, { part: token, walker: this });
|
|
163
172
|
}
|
|
164
173
|
catch (e) {
|
|
174
|
+
this.sourcePosition = start; // Reset source position on validation failure
|
|
165
175
|
if (e instanceof errors_1.RGXPartValidationFailedError) {
|
|
166
|
-
token.afterValidationFailure?.(e,
|
|
176
|
+
const control = token.afterValidationFailure?.(e, { part: token, walker: this });
|
|
177
|
+
if (control === "stop") {
|
|
178
|
+
this._stopped = true;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
if (control === "skip") {
|
|
182
|
+
this.tokenPosition++;
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
// Handling silent is pointless here since it won't add a capture in either case, so we don't check for it.
|
|
167
186
|
}
|
|
168
187
|
throw e;
|
|
169
188
|
}
|
|
@@ -179,7 +198,7 @@ class RGXWalker {
|
|
|
179
198
|
}
|
|
180
199
|
// Notify Part after capture
|
|
181
200
|
if (isPart) {
|
|
182
|
-
token.afterCapture?.(captureResult,
|
|
201
|
+
token.afterCapture?.(captureResult, { part: token, walker: this });
|
|
183
202
|
}
|
|
184
203
|
if (!this.infinite || this.tokenPosition < this.tokens.length - 1) {
|
|
185
204
|
this.tokenPosition++;
|
|
@@ -213,7 +232,8 @@ class RGXWalker {
|
|
|
213
232
|
return this;
|
|
214
233
|
}
|
|
215
234
|
walk() {
|
|
216
|
-
|
|
235
|
+
this.stepToToken(() => false);
|
|
236
|
+
return this.reduced;
|
|
217
237
|
}
|
|
218
238
|
// Clone method
|
|
219
239
|
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>) => RGXPartControl) | null;
|
|
27
|
+
afterValidationFailure: ((e: RGXPartValidationFailedError, context: RGXPartContext<R, S, T>) => RGXPartControl) | 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";
|