path-to-regexp 6.2.2 → 7.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 +141 -166
- package/dist/index.d.ts +86 -74
- package/dist/index.js +323 -302
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
- package/dist.es2015/index.js +0 -400
- package/dist.es2015/index.js.map +0 -1
package/dist/index.js
CHANGED
@@ -1,397 +1,420 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.TokenData = void 0;
|
4
|
+
exports.parse = parse;
|
5
|
+
exports.compile = compile;
|
6
|
+
exports.match = match;
|
7
|
+
exports.pathToRegexp = pathToRegexp;
|
8
|
+
const DEFAULT_DELIMITER = "/";
|
9
|
+
const NOOP_VALUE = (value) => value;
|
10
|
+
const ID_CHAR = /^\p{XID_Continue}$/u;
|
11
|
+
const DEBUG_URL = "https://git.new/pathToRegexpError";
|
12
|
+
const SIMPLE_TOKENS = {
|
13
|
+
"!": "!",
|
14
|
+
"@": "@",
|
15
|
+
";": ";",
|
16
|
+
",": ",",
|
17
|
+
"*": "*",
|
18
|
+
"+": "+",
|
19
|
+
"?": "?",
|
20
|
+
"{": "{",
|
21
|
+
"}": "}",
|
22
|
+
};
|
4
23
|
/**
|
5
24
|
* Tokenize input string.
|
6
25
|
*/
|
7
26
|
function lexer(str) {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
27
|
+
const chars = [...str];
|
28
|
+
const tokens = [];
|
29
|
+
let i = 0;
|
30
|
+
while (i < chars.length) {
|
31
|
+
const value = chars[i];
|
32
|
+
const type = SIMPLE_TOKENS[value];
|
33
|
+
if (type) {
|
34
|
+
tokens.push({ type, index: i++, value });
|
14
35
|
continue;
|
15
36
|
}
|
16
|
-
if (
|
17
|
-
tokens.push({ type: "
|
37
|
+
if (value === "\\") {
|
38
|
+
tokens.push({ type: "ESCAPED", index: i++, value: chars[i++] });
|
18
39
|
continue;
|
19
40
|
}
|
20
|
-
if (
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}
|
28
|
-
if (char === ":") {
|
29
|
-
var name = "";
|
30
|
-
var j = i + 1;
|
31
|
-
while (j < str.length) {
|
32
|
-
var code = str.charCodeAt(j);
|
33
|
-
if (
|
34
|
-
// `0-9`
|
35
|
-
(code >= 48 && code <= 57) ||
|
36
|
-
// `A-Z`
|
37
|
-
(code >= 65 && code <= 90) ||
|
38
|
-
// `a-z`
|
39
|
-
(code >= 97 && code <= 122) ||
|
40
|
-
// `_`
|
41
|
-
code === 95) {
|
42
|
-
name += str[j++];
|
43
|
-
continue;
|
44
|
-
}
|
45
|
-
break;
|
41
|
+
if (value === ":") {
|
42
|
+
let name = "";
|
43
|
+
while (ID_CHAR.test(chars[++i])) {
|
44
|
+
name += chars[i];
|
45
|
+
}
|
46
|
+
if (!name) {
|
47
|
+
throw new TypeError(`Missing parameter name at ${i}`);
|
46
48
|
}
|
47
|
-
if (!name)
|
48
|
-
throw new TypeError("Missing parameter name at ".concat(i));
|
49
49
|
tokens.push({ type: "NAME", index: i, value: name });
|
50
|
-
i = j;
|
51
50
|
continue;
|
52
51
|
}
|
53
|
-
if (
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
if (
|
58
|
-
throw new TypeError(
|
52
|
+
if (value === "(") {
|
53
|
+
const pos = i++;
|
54
|
+
let count = 1;
|
55
|
+
let pattern = "";
|
56
|
+
if (chars[i] === "?") {
|
57
|
+
throw new TypeError(`Pattern cannot start with "?" at ${i}`);
|
59
58
|
}
|
60
|
-
while (
|
61
|
-
if (
|
62
|
-
pattern +=
|
59
|
+
while (i < chars.length) {
|
60
|
+
if (chars[i] === "\\") {
|
61
|
+
pattern += chars[i++] + chars[i++];
|
63
62
|
continue;
|
64
63
|
}
|
65
|
-
if (
|
64
|
+
if (chars[i] === ")") {
|
66
65
|
count--;
|
67
66
|
if (count === 0) {
|
68
|
-
|
67
|
+
i++;
|
69
68
|
break;
|
70
69
|
}
|
71
70
|
}
|
72
|
-
else if (
|
71
|
+
else if (chars[i] === "(") {
|
73
72
|
count++;
|
74
|
-
if (
|
75
|
-
throw new TypeError(
|
73
|
+
if (chars[i + 1] !== "?") {
|
74
|
+
throw new TypeError(`Capturing groups are not allowed at ${i}`);
|
76
75
|
}
|
77
76
|
}
|
78
|
-
pattern +=
|
77
|
+
pattern += chars[i++];
|
79
78
|
}
|
80
79
|
if (count)
|
81
|
-
throw new TypeError(
|
80
|
+
throw new TypeError(`Unbalanced pattern at ${pos}`);
|
82
81
|
if (!pattern)
|
83
|
-
throw new TypeError(
|
82
|
+
throw new TypeError(`Missing pattern at ${pos}`);
|
84
83
|
tokens.push({ type: "PATTERN", index: i, value: pattern });
|
85
|
-
i = j;
|
86
84
|
continue;
|
87
85
|
}
|
88
|
-
tokens.push({ type: "CHAR", index: i, value:
|
86
|
+
tokens.push({ type: "CHAR", index: i, value: chars[i++] });
|
89
87
|
}
|
90
88
|
tokens.push({ type: "END", index: i, value: "" });
|
91
|
-
return tokens;
|
89
|
+
return new Iter(tokens);
|
92
90
|
}
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
var value = tryConsume(type);
|
91
|
+
class Iter {
|
92
|
+
constructor(tokens) {
|
93
|
+
this.tokens = tokens;
|
94
|
+
this.index = 0;
|
95
|
+
}
|
96
|
+
peek() {
|
97
|
+
return this.tokens[this.index];
|
98
|
+
}
|
99
|
+
tryConsume(type) {
|
100
|
+
const token = this.peek();
|
101
|
+
if (token.type !== type)
|
102
|
+
return;
|
103
|
+
this.index++;
|
104
|
+
return token.value;
|
105
|
+
}
|
106
|
+
consume(type) {
|
107
|
+
const value = this.tryConsume(type);
|
111
108
|
if (value !== undefined)
|
112
109
|
return value;
|
113
|
-
|
114
|
-
throw new TypeError(
|
115
|
-
}
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
while ((value = tryConsume("CHAR") || tryConsume("
|
110
|
+
const { type: nextType, index } = this.peek();
|
111
|
+
throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}: ${DEBUG_URL}`);
|
112
|
+
}
|
113
|
+
text() {
|
114
|
+
let result = "";
|
115
|
+
let value;
|
116
|
+
while ((value = this.tryConsume("CHAR") || this.tryConsume("ESCAPED"))) {
|
120
117
|
result += value;
|
121
118
|
}
|
122
119
|
return result;
|
123
|
-
}
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
120
|
+
}
|
121
|
+
modifier() {
|
122
|
+
return this.tryConsume("?") || this.tryConsume("*") || this.tryConsume("+");
|
123
|
+
}
|
124
|
+
}
|
125
|
+
/**
|
126
|
+
* Tokenized path instance. Can we passed around instead of string.
|
127
|
+
*/
|
128
|
+
class TokenData {
|
129
|
+
constructor(tokens, delimiter) {
|
130
|
+
this.tokens = tokens;
|
131
|
+
this.delimiter = delimiter;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
exports.TokenData = TokenData;
|
135
|
+
/**
|
136
|
+
* Parse a string for the raw tokens.
|
137
|
+
*/
|
138
|
+
function parse(str, options = {}) {
|
139
|
+
const { encodePath = NOOP_VALUE, delimiter = encodePath(DEFAULT_DELIMITER) } = options;
|
140
|
+
const tokens = [];
|
141
|
+
const it = lexer(str);
|
142
|
+
let key = 0;
|
143
|
+
do {
|
144
|
+
const path = it.text();
|
145
|
+
if (path)
|
146
|
+
tokens.push(encodePath(path));
|
147
|
+
const name = it.tryConsume("NAME");
|
148
|
+
const pattern = it.tryConsume("PATTERN");
|
128
149
|
if (name || pattern) {
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
prefix = "";
|
133
|
-
}
|
134
|
-
if (path) {
|
135
|
-
result.push(path);
|
136
|
-
path = "";
|
137
|
-
}
|
138
|
-
result.push({
|
139
|
-
name: name || key++,
|
140
|
-
prefix: prefix,
|
141
|
-
suffix: "",
|
142
|
-
pattern: pattern || defaultPattern,
|
143
|
-
modifier: tryConsume("MODIFIER") || "",
|
150
|
+
tokens.push({
|
151
|
+
name: name || String(key++),
|
152
|
+
pattern,
|
144
153
|
});
|
154
|
+
const next = it.peek();
|
155
|
+
if (next.type === "*") {
|
156
|
+
throw new TypeError(`Unexpected * at ${next.index}, you probably want \`/*\` or \`{/:foo}*\`: ${DEBUG_URL}`);
|
157
|
+
}
|
145
158
|
continue;
|
146
159
|
}
|
147
|
-
|
148
|
-
if (
|
149
|
-
|
160
|
+
const asterisk = it.tryConsume("*");
|
161
|
+
if (asterisk) {
|
162
|
+
tokens.push({
|
163
|
+
name: String(key++),
|
164
|
+
pattern: `(?:(?!${escape(delimiter)}).)*`,
|
165
|
+
modifier: "*",
|
166
|
+
separator: delimiter,
|
167
|
+
});
|
150
168
|
continue;
|
151
169
|
}
|
152
|
-
|
153
|
-
result.push(path);
|
154
|
-
path = "";
|
155
|
-
}
|
156
|
-
var open = tryConsume("OPEN");
|
170
|
+
const open = it.tryConsume("{");
|
157
171
|
if (open) {
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
172
|
+
const prefix = it.text();
|
173
|
+
const name = it.tryConsume("NAME");
|
174
|
+
const pattern = it.tryConsume("PATTERN");
|
175
|
+
const suffix = it.text();
|
176
|
+
const separator = it.tryConsume(";") && it.text();
|
177
|
+
it.consume("}");
|
178
|
+
const modifier = it.modifier();
|
179
|
+
tokens.push({
|
180
|
+
name: name || (pattern ? String(key++) : ""),
|
181
|
+
prefix: encodePath(prefix),
|
182
|
+
suffix: encodePath(suffix),
|
183
|
+
pattern,
|
184
|
+
modifier,
|
185
|
+
separator,
|
169
186
|
});
|
170
187
|
continue;
|
171
188
|
}
|
172
|
-
|
173
|
-
|
174
|
-
|
189
|
+
it.consume("END");
|
190
|
+
break;
|
191
|
+
} while (true);
|
192
|
+
return new TokenData(tokens, delimiter);
|
175
193
|
}
|
176
|
-
exports.parse = parse;
|
177
194
|
/**
|
178
195
|
* Compile a string to a template function for the path.
|
179
196
|
*/
|
180
|
-
function compile(
|
181
|
-
|
197
|
+
function compile(path, options = {}) {
|
198
|
+
const data = path instanceof TokenData ? path : parse(path, options);
|
199
|
+
return compileTokens(data, options);
|
182
200
|
}
|
183
|
-
exports.compile = compile;
|
184
201
|
/**
|
185
|
-
*
|
202
|
+
* Convert a single token into a path building function.
|
186
203
|
*/
|
187
|
-
function
|
188
|
-
if (
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
for (var i = 0; i < tokens.length; i++) {
|
200
|
-
var token = tokens[i];
|
201
|
-
if (typeof token === "string") {
|
202
|
-
path += token;
|
203
|
-
continue;
|
204
|
-
}
|
205
|
-
var value = data ? data[token.name] : undefined;
|
206
|
-
var optional = token.modifier === "?" || token.modifier === "*";
|
207
|
-
var repeat = token.modifier === "*" || token.modifier === "+";
|
208
|
-
if (Array.isArray(value)) {
|
209
|
-
if (!repeat) {
|
210
|
-
throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
|
211
|
-
}
|
212
|
-
if (value.length === 0) {
|
213
|
-
if (optional)
|
214
|
-
continue;
|
215
|
-
throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
|
216
|
-
}
|
217
|
-
for (var j = 0; j < value.length; j++) {
|
218
|
-
var segment = encode(value[j], token);
|
219
|
-
if (validate && !matches[i].test(segment)) {
|
220
|
-
throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
|
221
|
-
}
|
222
|
-
path += token.prefix + segment + token.suffix;
|
223
|
-
}
|
224
|
-
continue;
|
204
|
+
function tokenToFunction(token, encode) {
|
205
|
+
if (typeof token === "string") {
|
206
|
+
return () => token;
|
207
|
+
}
|
208
|
+
const encodeValue = encode || NOOP_VALUE;
|
209
|
+
const repeated = token.modifier === "+" || token.modifier === "*";
|
210
|
+
const optional = token.modifier === "?" || token.modifier === "*";
|
211
|
+
const { prefix = "", suffix = "", separator = suffix + prefix } = token;
|
212
|
+
if (encode && repeated) {
|
213
|
+
const stringify = (value, index) => {
|
214
|
+
if (typeof value !== "string") {
|
215
|
+
throw new TypeError(`Expected "${token.name}/${index}" to be a string`);
|
225
216
|
}
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
}
|
231
|
-
path += token.prefix + segment + token.suffix;
|
232
|
-
continue;
|
217
|
+
return encodeValue(value);
|
218
|
+
};
|
219
|
+
const compile = (value) => {
|
220
|
+
if (!Array.isArray(value)) {
|
221
|
+
throw new TypeError(`Expected "${token.name}" to be an array`);
|
233
222
|
}
|
234
|
-
if (
|
235
|
-
|
236
|
-
|
237
|
-
|
223
|
+
if (value.length === 0)
|
224
|
+
return "";
|
225
|
+
return prefix + value.map(stringify).join(separator) + suffix;
|
226
|
+
};
|
227
|
+
if (optional) {
|
228
|
+
return (data) => {
|
229
|
+
const value = data[token.name];
|
230
|
+
if (value == null)
|
231
|
+
return "";
|
232
|
+
return value.length ? compile(value) : "";
|
233
|
+
};
|
238
234
|
}
|
239
|
-
return
|
235
|
+
return (data) => {
|
236
|
+
const value = data[token.name];
|
237
|
+
return compile(value);
|
238
|
+
};
|
239
|
+
}
|
240
|
+
const stringify = (value) => {
|
241
|
+
if (typeof value !== "string") {
|
242
|
+
throw new TypeError(`Expected "${token.name}" to be a string`);
|
243
|
+
}
|
244
|
+
return prefix + encodeValue(value) + suffix;
|
245
|
+
};
|
246
|
+
if (optional) {
|
247
|
+
return (data) => {
|
248
|
+
const value = data[token.name];
|
249
|
+
if (value == null)
|
250
|
+
return "";
|
251
|
+
return stringify(value);
|
252
|
+
};
|
253
|
+
}
|
254
|
+
return (data) => {
|
255
|
+
const value = data[token.name];
|
256
|
+
return stringify(value);
|
240
257
|
};
|
241
258
|
}
|
242
|
-
exports.tokensToFunction = tokensToFunction;
|
243
259
|
/**
|
244
|
-
*
|
260
|
+
* Transform tokens into a path building function.
|
245
261
|
*/
|
246
|
-
function
|
247
|
-
|
248
|
-
|
249
|
-
|
262
|
+
function compileTokens(data, options) {
|
263
|
+
const { encode = encodeURIComponent, loose = true, validate = true, strict = false, } = options;
|
264
|
+
const flags = toFlags(options);
|
265
|
+
const stringify = toStringify(loose, data.delimiter);
|
266
|
+
const sources = toRegExpSource(data, stringify, [], flags, strict);
|
267
|
+
// Compile all the tokens into regexps.
|
268
|
+
const encoders = data.tokens.map((token, index) => {
|
269
|
+
const fn = tokenToFunction(token, encode);
|
270
|
+
if (!validate || typeof token === "string")
|
271
|
+
return fn;
|
272
|
+
const validRe = new RegExp(`^${sources[index]}$`, flags);
|
273
|
+
return (data) => {
|
274
|
+
const value = fn(data);
|
275
|
+
if (!validRe.test(value)) {
|
276
|
+
throw new TypeError(`Invalid value for "${token.name}": ${JSON.stringify(value)}`);
|
277
|
+
}
|
278
|
+
return value;
|
279
|
+
};
|
280
|
+
});
|
281
|
+
return function path(data = {}) {
|
282
|
+
let path = "";
|
283
|
+
for (const encoder of encoders)
|
284
|
+
path += encoder(data);
|
285
|
+
return path;
|
286
|
+
};
|
250
287
|
}
|
251
|
-
exports.match = match;
|
252
288
|
/**
|
253
|
-
* Create
|
289
|
+
* Create path match function from `path-to-regexp` spec.
|
254
290
|
*/
|
255
|
-
function
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
291
|
+
function match(path, options = {}) {
|
292
|
+
const { decode = decodeURIComponent, loose = true } = options;
|
293
|
+
const data = path instanceof TokenData ? path : parse(path, options);
|
294
|
+
const stringify = toStringify(loose, data.delimiter);
|
295
|
+
const keys = [];
|
296
|
+
const re = tokensToRegexp(data, keys, options);
|
297
|
+
const decoders = keys.map((key) => {
|
298
|
+
if (decode && (key.modifier === "+" || key.modifier === "*")) {
|
299
|
+
const { prefix = "", suffix = "", separator = suffix + prefix } = key;
|
300
|
+
const re = new RegExp(stringify(separator), "g");
|
301
|
+
return (value) => value.split(re).map(decode);
|
302
|
+
}
|
303
|
+
return decode || NOOP_VALUE;
|
304
|
+
});
|
305
|
+
return function match(input) {
|
306
|
+
const m = re.exec(input);
|
260
307
|
if (!m)
|
261
308
|
return false;
|
262
|
-
|
263
|
-
|
264
|
-
|
309
|
+
const { 0: path, index } = m;
|
310
|
+
const params = Object.create(null);
|
311
|
+
for (let i = 1; i < m.length; i++) {
|
265
312
|
if (m[i] === undefined)
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
return decode(value, key);
|
271
|
-
});
|
272
|
-
}
|
273
|
-
else {
|
274
|
-
params[key.name] = decode(m[i], key);
|
275
|
-
}
|
276
|
-
};
|
277
|
-
for (var i = 1; i < m.length; i++) {
|
278
|
-
_loop_1(i);
|
313
|
+
continue;
|
314
|
+
const key = keys[i - 1];
|
315
|
+
const decoder = decoders[i - 1];
|
316
|
+
params[key.name] = decoder(m[i]);
|
279
317
|
}
|
280
|
-
return { path
|
318
|
+
return { path, index, params };
|
281
319
|
};
|
282
320
|
}
|
283
|
-
exports.regexpToFunction = regexpToFunction;
|
284
321
|
/**
|
285
322
|
* Escape a regular expression string.
|
286
323
|
*/
|
287
|
-
function
|
288
|
-
return str.replace(/([
|
324
|
+
function escape(str) {
|
325
|
+
return str.replace(/([.+*?^${}()[\]|/\\])/g, "\\$1");
|
289
326
|
}
|
290
327
|
/**
|
291
|
-
*
|
328
|
+
* Escape and repeat loose characters for regular expressions.
|
292
329
|
*/
|
293
|
-
function
|
294
|
-
|
330
|
+
function looseReplacer(value, loose) {
|
331
|
+
const escaped = escape(value);
|
332
|
+
return loose ? `(?:${escaped})+(?!${escaped})` : escaped;
|
295
333
|
}
|
296
334
|
/**
|
297
|
-
*
|
335
|
+
* Encode all non-delimiter characters using the encode function.
|
298
336
|
*/
|
299
|
-
function
|
300
|
-
if (!
|
301
|
-
return
|
302
|
-
|
303
|
-
|
304
|
-
var execResult = groupsRegex.exec(path.source);
|
305
|
-
while (execResult) {
|
306
|
-
keys.push({
|
307
|
-
// Use parenthesized substring match if available, index otherwise
|
308
|
-
name: execResult[1] || index++,
|
309
|
-
prefix: "",
|
310
|
-
suffix: "",
|
311
|
-
modifier: "",
|
312
|
-
pattern: "",
|
313
|
-
});
|
314
|
-
execResult = groupsRegex.exec(path.source);
|
315
|
-
}
|
316
|
-
return path;
|
337
|
+
function toStringify(loose, delimiter) {
|
338
|
+
if (!loose)
|
339
|
+
return escape;
|
340
|
+
const re = new RegExp(`(?:(?!${escape(delimiter)}).)+|(.)`, "g");
|
341
|
+
return (value) => value.replace(re, looseReplacer);
|
317
342
|
}
|
318
343
|
/**
|
319
|
-
*
|
344
|
+
* Get the flags for a regexp from the options.
|
320
345
|
*/
|
321
|
-
function
|
322
|
-
|
323
|
-
return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
|
346
|
+
function toFlags(options) {
|
347
|
+
return options.sensitive ? "" : "i";
|
324
348
|
}
|
325
349
|
/**
|
326
|
-
*
|
350
|
+
* Expose a function for taking tokens and returning a RegExp.
|
327
351
|
*/
|
328
|
-
function
|
329
|
-
|
352
|
+
function tokensToRegexp(data, keys, options) {
|
353
|
+
const { trailing = true, loose = true, start = true, end = true, strict = false, } = options;
|
354
|
+
const flags = toFlags(options);
|
355
|
+
const stringify = toStringify(loose, data.delimiter);
|
356
|
+
const sources = toRegExpSource(data, stringify, keys, flags, strict);
|
357
|
+
let pattern = start ? "^" : "";
|
358
|
+
pattern += sources.join("");
|
359
|
+
if (trailing)
|
360
|
+
pattern += `(?:${stringify(data.delimiter)})?`;
|
361
|
+
pattern += end ? "$" : `(?=${escape(data.delimiter)}|$)`;
|
362
|
+
return new RegExp(pattern, flags);
|
330
363
|
}
|
331
364
|
/**
|
332
|
-
*
|
365
|
+
* Convert a token into a regexp string (re-used for path validation).
|
333
366
|
*/
|
334
|
-
function
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
var route = start ? "^" : "";
|
340
|
-
// Iterate over the tokens and create our regexp string.
|
341
|
-
for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
|
342
|
-
var token = tokens_1[_i];
|
367
|
+
function toRegExpSource(data, stringify, keys, flags, strict) {
|
368
|
+
const defaultPattern = `(?:(?!${escape(data.delimiter)}).)+?`;
|
369
|
+
let backtrack = "";
|
370
|
+
let safe = true;
|
371
|
+
return data.tokens.map((token, index) => {
|
343
372
|
if (typeof token === "string") {
|
344
|
-
|
373
|
+
backtrack = token;
|
374
|
+
return stringify(token);
|
345
375
|
}
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
376
|
+
const { prefix = "", suffix = "", separator = suffix + prefix, modifier = "", } = token;
|
377
|
+
const pre = stringify(prefix);
|
378
|
+
const post = stringify(suffix);
|
379
|
+
if (token.name) {
|
380
|
+
const pattern = token.pattern ? `(?:${token.pattern})` : defaultPattern;
|
381
|
+
const re = checkPattern(pattern, token.name, flags);
|
382
|
+
safe || (safe = safePattern(re, prefix || backtrack));
|
383
|
+
if (!safe) {
|
384
|
+
throw new TypeError(`Ambiguous pattern for "${token.name}": ${DEBUG_URL}`);
|
385
|
+
}
|
386
|
+
safe = !strict || safePattern(re, suffix);
|
387
|
+
backtrack = "";
|
388
|
+
keys.push(token);
|
389
|
+
if (modifier === "+" || modifier === "*") {
|
390
|
+
const mod = modifier === "*" ? "?" : "";
|
391
|
+
const sep = stringify(separator);
|
392
|
+
if (!sep) {
|
393
|
+
throw new TypeError(`Missing separator for "${token.name}": ${DEBUG_URL}`);
|
360
394
|
}
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
}
|
365
|
-
else {
|
366
|
-
route += "(".concat(token.pattern, ")").concat(token.modifier);
|
367
|
-
}
|
395
|
+
safe || (safe = !strict || safePattern(re, separator));
|
396
|
+
if (!safe) {
|
397
|
+
throw new TypeError(`Ambiguous pattern for "${token.name}" separator: ${DEBUG_URL}`);
|
368
398
|
}
|
399
|
+
safe = !strict;
|
400
|
+
return `(?:${pre}(${pattern}(?:${sep}${pattern})*)${post})${mod}`;
|
369
401
|
}
|
370
|
-
|
371
|
-
route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
|
372
|
-
}
|
402
|
+
return `(?:${pre}(${pattern})${post})${modifier}`;
|
373
403
|
}
|
404
|
+
return `(?:${pre}${post})${modifier}`;
|
405
|
+
});
|
406
|
+
}
|
407
|
+
function checkPattern(pattern, name, flags) {
|
408
|
+
try {
|
409
|
+
return new RegExp(`^${pattern}$`, flags);
|
374
410
|
}
|
375
|
-
|
376
|
-
|
377
|
-
route += "".concat(delimiterRe, "?");
|
378
|
-
route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
|
379
|
-
}
|
380
|
-
else {
|
381
|
-
var endToken = tokens[tokens.length - 1];
|
382
|
-
var isEndDelimited = typeof endToken === "string"
|
383
|
-
? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
|
384
|
-
: endToken === undefined;
|
385
|
-
if (!strict) {
|
386
|
-
route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
|
387
|
-
}
|
388
|
-
if (!isEndDelimited) {
|
389
|
-
route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
|
390
|
-
}
|
411
|
+
catch (err) {
|
412
|
+
throw new TypeError(`Invalid pattern for "${name}": ${err.message}`);
|
391
413
|
}
|
392
|
-
return new RegExp(route, flags(options));
|
393
414
|
}
|
394
|
-
|
415
|
+
function safePattern(re, value) {
|
416
|
+
return value ? !re.test(value) : false;
|
417
|
+
}
|
395
418
|
/**
|
396
419
|
* Normalize the given path string, returning a regular expression.
|
397
420
|
*
|
@@ -399,12 +422,10 @@ exports.tokensToRegexp = tokensToRegexp;
|
|
399
422
|
* placeholder key descriptions. For example, using `/user/:id`, `keys` will
|
400
423
|
* contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
|
401
424
|
*/
|
402
|
-
function pathToRegexp(path,
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
return stringToRegexp(path, keys, options);
|
425
|
+
function pathToRegexp(path, options = {}) {
|
426
|
+
const data = path instanceof TokenData ? path : parse(path, options);
|
427
|
+
const keys = [];
|
428
|
+
const regexp = tokensToRegexp(data, keys, options);
|
429
|
+
return Object.assign(regexp, { keys });
|
408
430
|
}
|
409
|
-
exports.pathToRegexp = pathToRegexp;
|
410
431
|
//# sourceMappingURL=index.js.map
|