path-to-regexp 7.0.0 → 8.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 +79 -184
- package/dist/index.d.ts +51 -73
- package/dist/index.js +267 -289
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
@@ -1,101 +1,129 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
6
|
+
};
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
12
|
+
};
|
13
|
+
var _Iter_peek;
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
15
|
+
exports.TokenData = void 0;
|
16
|
+
exports.parse = parse;
|
17
|
+
exports.compile = compile;
|
18
|
+
exports.match = match;
|
4
19
|
const DEFAULT_DELIMITER = "/";
|
5
20
|
const NOOP_VALUE = (value) => value;
|
6
|
-
const
|
21
|
+
const ID_START = /^[$_\p{ID_Start}]$/u;
|
22
|
+
const ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
|
23
|
+
const DEBUG_URL = "https://git.new/pathToRegexpError";
|
7
24
|
const SIMPLE_TOKENS = {
|
8
|
-
|
9
|
-
"@": "@",
|
10
|
-
";": ";",
|
11
|
-
",": ",",
|
12
|
-
"*": "*",
|
13
|
-
"+": "+",
|
14
|
-
"?": "?",
|
25
|
+
// Groups.
|
15
26
|
"{": "{",
|
16
27
|
"}": "}",
|
28
|
+
// Reserved.
|
29
|
+
"(": "(",
|
30
|
+
")": ")",
|
31
|
+
"[": "[",
|
32
|
+
"]": "]",
|
33
|
+
"+": "+",
|
34
|
+
"?": "?",
|
35
|
+
"!": "!",
|
17
36
|
};
|
37
|
+
/**
|
38
|
+
* Escape a regular expression string.
|
39
|
+
*/
|
40
|
+
function escape(str) {
|
41
|
+
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
|
42
|
+
}
|
43
|
+
/**
|
44
|
+
* Get the flags for a regexp from the options.
|
45
|
+
*/
|
46
|
+
function toFlags(options) {
|
47
|
+
return options.sensitive ? "s" : "is";
|
48
|
+
}
|
18
49
|
/**
|
19
50
|
* Tokenize input string.
|
20
51
|
*/
|
21
|
-
function lexer(str) {
|
52
|
+
function* lexer(str) {
|
22
53
|
const chars = [...str];
|
23
|
-
const tokens = [];
|
24
54
|
let i = 0;
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
}
|
32
|
-
if (value === "\\") {
|
33
|
-
tokens.push({ type: "ESCAPED", index: i++, value: chars[i++] });
|
34
|
-
continue;
|
35
|
-
}
|
36
|
-
if (value === ":") {
|
37
|
-
let name = "";
|
38
|
-
while (ID_CHAR.test(chars[++i])) {
|
39
|
-
name += chars[i];
|
40
|
-
}
|
41
|
-
if (!name) {
|
42
|
-
throw new TypeError(`Missing parameter name at ${i}`);
|
55
|
+
function name() {
|
56
|
+
let value = "";
|
57
|
+
if (ID_START.test(chars[++i])) {
|
58
|
+
value += chars[i];
|
59
|
+
while (ID_CONTINUE.test(chars[++i])) {
|
60
|
+
value += chars[i];
|
43
61
|
}
|
44
|
-
tokens.push({ type: "NAME", index: i, value: name });
|
45
|
-
continue;
|
46
62
|
}
|
47
|
-
if (
|
48
|
-
|
49
|
-
let count = 1;
|
50
|
-
let pattern = "";
|
51
|
-
if (chars[i] === "?") {
|
52
|
-
throw new TypeError(`Pattern cannot start with "?" at ${i}`);
|
53
|
-
}
|
63
|
+
else if (chars[i] === '"') {
|
64
|
+
let pos = i;
|
54
65
|
while (i < chars.length) {
|
55
|
-
if (chars[i] === "
|
56
|
-
|
57
|
-
|
66
|
+
if (chars[++i] === '"') {
|
67
|
+
i++;
|
68
|
+
pos = 0;
|
69
|
+
break;
|
58
70
|
}
|
59
|
-
if (chars[i] === "
|
60
|
-
|
61
|
-
if (count === 0) {
|
62
|
-
i++;
|
63
|
-
break;
|
64
|
-
}
|
71
|
+
if (chars[i] === "\\") {
|
72
|
+
value += chars[++i];
|
65
73
|
}
|
66
|
-
else
|
67
|
-
|
68
|
-
if (chars[i + 1] !== "?") {
|
69
|
-
throw new TypeError(`Capturing groups are not allowed at ${i}`);
|
70
|
-
}
|
74
|
+
else {
|
75
|
+
value += chars[i];
|
71
76
|
}
|
72
|
-
pattern += chars[i++];
|
73
77
|
}
|
74
|
-
if (
|
75
|
-
throw new TypeError(`
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
if (pos) {
|
79
|
+
throw new TypeError(`Unterminated quote at ${pos}: ${DEBUG_URL}`);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
if (!value) {
|
83
|
+
throw new TypeError(`Missing parameter name at ${i}: ${DEBUG_URL}`);
|
84
|
+
}
|
85
|
+
return value;
|
86
|
+
}
|
87
|
+
while (i < chars.length) {
|
88
|
+
const value = chars[i];
|
89
|
+
const type = SIMPLE_TOKENS[value];
|
90
|
+
if (type) {
|
91
|
+
yield { type, index: i++, value };
|
92
|
+
}
|
93
|
+
else if (value === "\\") {
|
94
|
+
yield { type: "ESCAPED", index: i++, value: chars[i++] };
|
95
|
+
}
|
96
|
+
else if (value === ":") {
|
97
|
+
const value = name();
|
98
|
+
yield { type: "PARAM", index: i, value };
|
99
|
+
}
|
100
|
+
else if (value === "*") {
|
101
|
+
const value = name();
|
102
|
+
yield { type: "WILDCARD", index: i, value };
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
yield { type: "CHAR", index: i, value: chars[i++] };
|
80
106
|
}
|
81
|
-
tokens.push({ type: "CHAR", index: i, value: chars[i++] });
|
82
107
|
}
|
83
|
-
|
84
|
-
return new Iter(tokens);
|
108
|
+
return { type: "END", index: i, value: "" };
|
85
109
|
}
|
86
110
|
class Iter {
|
87
111
|
constructor(tokens) {
|
88
112
|
this.tokens = tokens;
|
89
|
-
this
|
113
|
+
_Iter_peek.set(this, void 0);
|
90
114
|
}
|
91
115
|
peek() {
|
92
|
-
|
116
|
+
if (!__classPrivateFieldGet(this, _Iter_peek, "f")) {
|
117
|
+
const next = this.tokens.next();
|
118
|
+
__classPrivateFieldSet(this, _Iter_peek, next.value, "f");
|
119
|
+
}
|
120
|
+
return __classPrivateFieldGet(this, _Iter_peek, "f");
|
93
121
|
}
|
94
122
|
tryConsume(type) {
|
95
123
|
const token = this.peek();
|
96
124
|
if (token.type !== type)
|
97
125
|
return;
|
98
|
-
this.
|
126
|
+
__classPrivateFieldSet(this, _Iter_peek, undefined, "f"); // Reset after consumed.
|
99
127
|
return token.value;
|
100
128
|
}
|
101
129
|
consume(type) {
|
@@ -103,7 +131,7 @@ class Iter {
|
|
103
131
|
if (value !== undefined)
|
104
132
|
return value;
|
105
133
|
const { type: nextType, index } = this.peek();
|
106
|
-
throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}:
|
134
|
+
throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}: ${DEBUG_URL}`);
|
107
135
|
}
|
108
136
|
text() {
|
109
137
|
let result = "";
|
@@ -113,17 +141,14 @@ class Iter {
|
|
113
141
|
}
|
114
142
|
return result;
|
115
143
|
}
|
116
|
-
modifier() {
|
117
|
-
return (this.tryConsume("?") || this.tryConsume("*") || this.tryConsume("+") || "");
|
118
|
-
}
|
119
144
|
}
|
145
|
+
_Iter_peek = new WeakMap();
|
120
146
|
/**
|
121
|
-
* Tokenized path instance.
|
147
|
+
* Tokenized path instance.
|
122
148
|
*/
|
123
149
|
class TokenData {
|
124
|
-
constructor(tokens
|
150
|
+
constructor(tokens) {
|
125
151
|
this.tokens = tokens;
|
126
|
-
this.delimiter = delimiter;
|
127
152
|
}
|
128
153
|
}
|
129
154
|
exports.TokenData = TokenData;
|
@@ -131,179 +156,154 @@ exports.TokenData = TokenData;
|
|
131
156
|
* Parse a string for the raw tokens.
|
132
157
|
*/
|
133
158
|
function parse(str, options = {}) {
|
134
|
-
const {
|
135
|
-
const
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
const next = it.peek();
|
150
|
-
if (next.type === "*") {
|
151
|
-
throw new TypeError(`Unexpected * at ${next.index}, you probably want \`/*\` or \`{/:foo}*\`: https://git.new/pathToRegexpError`);
|
159
|
+
const { encodePath = NOOP_VALUE } = options;
|
160
|
+
const it = new Iter(lexer(str));
|
161
|
+
function consume(endType) {
|
162
|
+
const tokens = [];
|
163
|
+
while (true) {
|
164
|
+
const path = it.text();
|
165
|
+
if (path)
|
166
|
+
tokens.push({ type: "text", value: encodePath(path) });
|
167
|
+
const param = it.tryConsume("PARAM");
|
168
|
+
if (param) {
|
169
|
+
tokens.push({
|
170
|
+
type: "param",
|
171
|
+
name: param,
|
172
|
+
});
|
173
|
+
continue;
|
152
174
|
}
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
175
|
+
const wildcard = it.tryConsume("WILDCARD");
|
176
|
+
if (wildcard) {
|
177
|
+
tokens.push({
|
178
|
+
type: "wildcard",
|
179
|
+
name: wildcard,
|
180
|
+
});
|
181
|
+
continue;
|
182
|
+
}
|
183
|
+
const open = it.tryConsume("{");
|
184
|
+
if (open) {
|
185
|
+
tokens.push({
|
186
|
+
type: "group",
|
187
|
+
tokens: consume("}"),
|
188
|
+
});
|
189
|
+
continue;
|
190
|
+
}
|
191
|
+
it.consume(endType);
|
192
|
+
return tokens;
|
164
193
|
}
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
modifier,
|
180
|
-
separator,
|
181
|
-
});
|
182
|
-
continue;
|
194
|
+
}
|
195
|
+
const tokens = consume("END");
|
196
|
+
return new TokenData(tokens);
|
197
|
+
}
|
198
|
+
/**
|
199
|
+
* Transform tokens into a path building function.
|
200
|
+
*/
|
201
|
+
function $compile(data, options) {
|
202
|
+
const { encode = encodeURIComponent, delimiter = DEFAULT_DELIMITER } = options;
|
203
|
+
const fn = tokensToFunction(data.tokens, delimiter, encode);
|
204
|
+
return function path(data = {}) {
|
205
|
+
const [path, ...missing] = fn(data);
|
206
|
+
if (missing.length) {
|
207
|
+
throw new TypeError(`Missing parameters: ${missing.join(", ")}`);
|
183
208
|
}
|
184
|
-
|
185
|
-
|
186
|
-
} while (true);
|
187
|
-
return new TokenData(tokens, delimiter);
|
209
|
+
return path;
|
210
|
+
};
|
188
211
|
}
|
189
|
-
exports.parse = parse;
|
190
212
|
/**
|
191
213
|
* Compile a string to a template function for the path.
|
192
214
|
*/
|
193
215
|
function compile(path, options = {}) {
|
194
|
-
|
195
|
-
|
216
|
+
return $compile(path instanceof TokenData ? path : parse(path, options), options);
|
217
|
+
}
|
218
|
+
function tokensToFunction(tokens, delimiter, encode) {
|
219
|
+
const encoders = tokens.map((token) => tokenToFunction(token, delimiter, encode));
|
220
|
+
return (data) => {
|
221
|
+
const result = [""];
|
222
|
+
for (const encoder of encoders) {
|
223
|
+
const [value, ...extras] = encoder(data);
|
224
|
+
result[0] += value;
|
225
|
+
result.push(...extras);
|
226
|
+
}
|
227
|
+
return result;
|
228
|
+
};
|
196
229
|
}
|
197
|
-
exports.compile = compile;
|
198
230
|
/**
|
199
231
|
* Convert a single token into a path building function.
|
200
232
|
*/
|
201
|
-
function tokenToFunction(token, encode) {
|
202
|
-
if (
|
203
|
-
return () => token;
|
204
|
-
|
205
|
-
|
206
|
-
const repeated = token.modifier === "+" || token.modifier === "*";
|
207
|
-
const optional = token.modifier === "?" || token.modifier === "*";
|
208
|
-
const { prefix = "", suffix = "", separator = "" } = token;
|
209
|
-
if (encode && repeated) {
|
210
|
-
const stringify = (value, index) => {
|
211
|
-
if (typeof value !== "string") {
|
212
|
-
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
213
|
-
}
|
214
|
-
return encodeValue(value);
|
215
|
-
};
|
216
|
-
const compile = (value) => {
|
217
|
-
if (!Array.isArray(value)) {
|
218
|
-
throw new TypeError(`Expected "${token.name}" to be an array`);
|
219
|
-
}
|
220
|
-
if (value.length === 0)
|
221
|
-
return "";
|
222
|
-
return prefix + value.map(stringify).join(separator) + suffix;
|
223
|
-
};
|
224
|
-
if (optional) {
|
225
|
-
return (data) => {
|
226
|
-
const value = data[token.name];
|
227
|
-
if (value == null)
|
228
|
-
return "";
|
229
|
-
return value.length ? compile(value) : "";
|
230
|
-
};
|
231
|
-
}
|
233
|
+
function tokenToFunction(token, delimiter, encode) {
|
234
|
+
if (token.type === "text")
|
235
|
+
return () => [token.value];
|
236
|
+
if (token.type === "group") {
|
237
|
+
const fn = tokensToFunction(token.tokens, delimiter, encode);
|
232
238
|
return (data) => {
|
233
|
-
const value = data
|
234
|
-
|
239
|
+
const [value, ...missing] = fn(data);
|
240
|
+
if (!missing.length)
|
241
|
+
return [value];
|
242
|
+
return [""];
|
235
243
|
};
|
236
244
|
}
|
237
|
-
const
|
238
|
-
|
239
|
-
throw new TypeError(`Expected "${token.name}" to be a string`);
|
240
|
-
}
|
241
|
-
return prefix + encodeValue(value) + suffix;
|
242
|
-
};
|
243
|
-
if (optional) {
|
245
|
+
const encodeValue = encode || NOOP_VALUE;
|
246
|
+
if (token.type === "wildcard" && encode !== false) {
|
244
247
|
return (data) => {
|
245
248
|
const value = data[token.name];
|
246
249
|
if (value == null)
|
247
|
-
return "";
|
248
|
-
|
250
|
+
return ["", token.name];
|
251
|
+
if (!Array.isArray(value) || value.length === 0) {
|
252
|
+
throw new TypeError(`Expected "${token.name}" to be a non-empty array`);
|
253
|
+
}
|
254
|
+
return [
|
255
|
+
value
|
256
|
+
.map((value, index) => {
|
257
|
+
if (typeof value !== "string") {
|
258
|
+
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
259
|
+
}
|
260
|
+
return encodeValue(value);
|
261
|
+
})
|
262
|
+
.join(delimiter),
|
263
|
+
];
|
249
264
|
};
|
250
265
|
}
|
251
266
|
return (data) => {
|
252
267
|
const value = data[token.name];
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
function compileTokens(data, options) {
|
260
|
-
const { encode = encodeURIComponent, loose = true, validate = true, } = options;
|
261
|
-
const reFlags = flags(options);
|
262
|
-
const stringify = toStringify(loose, data.delimiter);
|
263
|
-
const keyToRegexp = toKeyRegexp(stringify, data.delimiter);
|
264
|
-
// Compile all the tokens into regexps.
|
265
|
-
const encoders = data.tokens.map((token) => {
|
266
|
-
const fn = tokenToFunction(token, encode);
|
267
|
-
if (!validate || typeof token === "string")
|
268
|
-
return fn;
|
269
|
-
const pattern = keyToRegexp(token);
|
270
|
-
const validRe = new RegExp(`^${pattern}$`, reFlags);
|
271
|
-
return (data) => {
|
272
|
-
const value = fn(data);
|
273
|
-
if (!validRe.test(value)) {
|
274
|
-
throw new TypeError(`Invalid value for "${token.name}": ${JSON.stringify(value)}`);
|
275
|
-
}
|
276
|
-
return value;
|
277
|
-
};
|
278
|
-
});
|
279
|
-
return function path(data = {}) {
|
280
|
-
let path = "";
|
281
|
-
for (const encoder of encoders)
|
282
|
-
path += encoder(data);
|
283
|
-
return path;
|
268
|
+
if (value == null)
|
269
|
+
return ["", token.name];
|
270
|
+
if (typeof value !== "string") {
|
271
|
+
throw new TypeError(`Expected "${token.name}" to be a string`);
|
272
|
+
}
|
273
|
+
return [encodeValue(value)];
|
284
274
|
};
|
285
275
|
}
|
286
276
|
/**
|
287
277
|
* Create path match function from `path-to-regexp` spec.
|
288
278
|
*/
|
289
|
-
function match(
|
290
|
-
const { decode = decodeURIComponent,
|
291
|
-
const
|
292
|
-
const
|
279
|
+
function $match(data, options = {}) {
|
280
|
+
const { decode = decodeURIComponent, delimiter = DEFAULT_DELIMITER, end = true, trailing = true, } = options;
|
281
|
+
const flags = toFlags(options);
|
282
|
+
const sources = [];
|
293
283
|
const keys = [];
|
294
|
-
const
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
return (value) => value.split(re).map(decode);
|
284
|
+
for (const { tokens } of data) {
|
285
|
+
for (const seq of flatten(tokens, 0, [])) {
|
286
|
+
const regexp = sequenceToRegExp(seq, delimiter, keys);
|
287
|
+
sources.push(regexp);
|
299
288
|
}
|
300
|
-
|
289
|
+
}
|
290
|
+
let pattern = `^(?:${sources.join("|")})`;
|
291
|
+
if (trailing)
|
292
|
+
pattern += `(?:${escape(delimiter)}$)?`;
|
293
|
+
pattern += end ? "$" : `(?=${escape(delimiter)}|$)`;
|
294
|
+
const re = new RegExp(pattern, flags);
|
295
|
+
const decoders = keys.map((key) => {
|
296
|
+
if (decode === false)
|
297
|
+
return NOOP_VALUE;
|
298
|
+
if (key.type === "param")
|
299
|
+
return decode;
|
300
|
+
return (value) => value.split(delimiter).map(decode);
|
301
301
|
});
|
302
|
-
return function match(
|
303
|
-
const m = re.exec(
|
302
|
+
return Object.assign(function match(input) {
|
303
|
+
const m = re.exec(input);
|
304
304
|
if (!m)
|
305
305
|
return false;
|
306
|
-
const { 0: path
|
306
|
+
const { 0: path } = m;
|
307
307
|
const params = Object.create(null);
|
308
308
|
for (let i = 1; i < m.length; i++) {
|
309
309
|
if (m[i] === undefined)
|
@@ -312,93 +312,71 @@ function match(path, options = {}) {
|
|
312
312
|
const decoder = decoders[i - 1];
|
313
313
|
params[key.name] = decoder(m[i]);
|
314
314
|
}
|
315
|
-
return { path,
|
316
|
-
};
|
317
|
-
}
|
318
|
-
exports.match = match;
|
319
|
-
/**
|
320
|
-
* Escape a regular expression string.
|
321
|
-
*/
|
322
|
-
function escape(str) {
|
323
|
-
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
|
315
|
+
return { path, params };
|
316
|
+
}, { re });
|
324
317
|
}
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
return loose ? `${escape(value)}+` : escape(value);
|
330
|
-
}
|
331
|
-
/**
|
332
|
-
* Encode all non-delimiter characters using the encode function.
|
333
|
-
*/
|
334
|
-
function toStringify(loose, delimiter) {
|
335
|
-
if (!loose)
|
336
|
-
return escape;
|
337
|
-
const re = new RegExp(`[^${escape(delimiter)}]+|(.)`, "g");
|
338
|
-
return (value) => value.replace(re, looseReplacer);
|
339
|
-
}
|
340
|
-
/**
|
341
|
-
* Get the flags for a regexp from the options.
|
342
|
-
*/
|
343
|
-
function flags(options) {
|
344
|
-
return options.sensitive ? "" : "i";
|
318
|
+
function match(path, options = {}) {
|
319
|
+
const paths = Array.isArray(path) ? path : [path];
|
320
|
+
const items = paths.map((path) => path instanceof TokenData ? path : parse(path, options));
|
321
|
+
return $match(items, options);
|
345
322
|
}
|
346
323
|
/**
|
347
|
-
*
|
324
|
+
* Generate a flat list of sequence tokens from the given tokens.
|
348
325
|
*/
|
349
|
-
function
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
else {
|
359
|
-
if (token.name)
|
360
|
-
keys.push(token);
|
361
|
-
pattern += keyToRegexp(token);
|
326
|
+
function* flatten(tokens, index, init) {
|
327
|
+
if (index === tokens.length) {
|
328
|
+
return yield init;
|
329
|
+
}
|
330
|
+
const token = tokens[index];
|
331
|
+
if (token.type === "group") {
|
332
|
+
const fork = init.slice();
|
333
|
+
for (const seq of flatten(token.tokens, 0, fork)) {
|
334
|
+
yield* flatten(tokens, index + 1, seq);
|
362
335
|
}
|
363
336
|
}
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
337
|
+
else {
|
338
|
+
init.push(token);
|
339
|
+
}
|
340
|
+
yield* flatten(tokens, index + 1, init);
|
368
341
|
}
|
369
342
|
/**
|
370
|
-
*
|
343
|
+
* Transform a flat sequence of tokens into a regular expression.
|
371
344
|
*/
|
372
|
-
function
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
const
|
378
|
-
if (
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
345
|
+
function sequenceToRegExp(tokens, delimiter, keys) {
|
346
|
+
let result = "";
|
347
|
+
let backtrack = "";
|
348
|
+
let isSafeSegmentParam = true;
|
349
|
+
for (let i = 0; i < tokens.length; i++) {
|
350
|
+
const token = tokens[i];
|
351
|
+
if (token.type === "text") {
|
352
|
+
result += escape(token.value);
|
353
|
+
backtrack = token.value;
|
354
|
+
isSafeSegmentParam || (isSafeSegmentParam = token.value.includes(delimiter));
|
355
|
+
continue;
|
356
|
+
}
|
357
|
+
if (token.type === "param" || token.type === "wildcard") {
|
358
|
+
if (!isSafeSegmentParam && !backtrack) {
|
359
|
+
throw new TypeError(`Missing text after "${token.name}": ${DEBUG_URL}`);
|
384
360
|
}
|
385
|
-
|
361
|
+
if (token.type === "param") {
|
362
|
+
result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
|
363
|
+
}
|
364
|
+
else {
|
365
|
+
result += `(.+)`;
|
366
|
+
}
|
367
|
+
keys.push(token);
|
368
|
+
backtrack = "";
|
369
|
+
isSafeSegmentParam = false;
|
370
|
+
continue;
|
386
371
|
}
|
387
|
-
|
388
|
-
|
372
|
+
}
|
373
|
+
return result;
|
389
374
|
}
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
*/
|
397
|
-
function pathToRegexp(path, options = {}) {
|
398
|
-
const data = path instanceof TokenData ? path : parse(path, options);
|
399
|
-
const keys = [];
|
400
|
-
const regexp = tokensToRegexp(data, keys, options);
|
401
|
-
return Object.assign(regexp, { keys });
|
375
|
+
function negate(delimiter, backtrack) {
|
376
|
+
const values = [delimiter, backtrack].filter(Boolean);
|
377
|
+
const isSimple = values.every((value) => value.length === 1);
|
378
|
+
if (isSimple)
|
379
|
+
return `[^${escape(values.join(""))}]`;
|
380
|
+
return `(?:(?!${values.map(escape).join("|")}).)`;
|
402
381
|
}
|
403
|
-
exports.pathToRegexp = pathToRegexp;
|
404
382
|
//# sourceMappingURL=index.js.map
|