path-to-regexp 7.1.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/dist/index.js CHANGED
@@ -1,106 +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
15
  exports.TokenData = void 0;
4
16
  exports.parse = parse;
5
17
  exports.compile = compile;
6
18
  exports.match = match;
7
- exports.pathToRegexp = pathToRegexp;
8
19
  const DEFAULT_DELIMITER = "/";
9
20
  const NOOP_VALUE = (value) => value;
10
- const ID_CHAR = /^\p{XID_Continue}$/u;
21
+ const ID_START = /^[$_\p{ID_Start}]$/u;
22
+ const ID_CONTINUE = /^[$\u200c\u200d\p{ID_Continue}]$/u;
11
23
  const DEBUG_URL = "https://git.new/pathToRegexpError";
12
24
  const SIMPLE_TOKENS = {
13
- "!": "!",
14
- "@": "@",
15
- ";": ";",
16
- ",": ",",
17
- "*": "*",
18
- "+": "+",
19
- "?": "?",
25
+ // Groups.
20
26
  "{": "{",
21
27
  "}": "}",
28
+ // Reserved.
29
+ "(": "(",
30
+ ")": ")",
31
+ "[": "[",
32
+ "]": "]",
33
+ "+": "+",
34
+ "?": "?",
35
+ "!": "!",
22
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
+ }
23
49
  /**
24
50
  * Tokenize input string.
25
51
  */
26
- function lexer(str) {
52
+ function* lexer(str) {
27
53
  const chars = [...str];
28
- const tokens = [];
29
54
  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 });
35
- continue;
36
- }
37
- if (value === "\\") {
38
- tokens.push({ type: "ESCAPED", index: i++, value: chars[i++] });
39
- continue;
40
- }
41
- if (value === ":") {
42
- let name = "";
43
- while (ID_CHAR.test(chars[++i])) {
44
- name += chars[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];
45
61
  }
46
- if (!name) {
47
- throw new TypeError(`Missing parameter name at ${i}`);
48
- }
49
- tokens.push({ type: "NAME", index: i, value: name });
50
- continue;
51
62
  }
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}`);
58
- }
63
+ else if (chars[i] === '"') {
64
+ let pos = i;
59
65
  while (i < chars.length) {
60
- if (chars[i] === "\\") {
61
- pattern += chars[i++] + chars[i++];
62
- continue;
66
+ if (chars[++i] === '"') {
67
+ i++;
68
+ pos = 0;
69
+ break;
63
70
  }
64
- if (chars[i] === ")") {
65
- count--;
66
- if (count === 0) {
67
- i++;
68
- break;
69
- }
71
+ if (chars[i] === "\\") {
72
+ value += chars[++i];
70
73
  }
71
- else if (chars[i] === "(") {
72
- count++;
73
- if (chars[i + 1] !== "?") {
74
- throw new TypeError(`Capturing groups are not allowed at ${i}`);
75
- }
74
+ else {
75
+ value += chars[i];
76
76
  }
77
- pattern += chars[i++];
78
77
  }
79
- if (count)
80
- throw new TypeError(`Unbalanced pattern at ${pos}`);
81
- if (!pattern)
82
- throw new TypeError(`Missing pattern at ${pos}`);
83
- tokens.push({ type: "PATTERN", index: i, value: pattern });
84
- continue;
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++] };
85
106
  }
86
- tokens.push({ type: "CHAR", index: i, value: chars[i++] });
87
107
  }
88
- tokens.push({ type: "END", index: i, value: "" });
89
- return new Iter(tokens);
108
+ return { type: "END", index: i, value: "" };
90
109
  }
91
110
  class Iter {
92
111
  constructor(tokens) {
93
112
  this.tokens = tokens;
94
- this.index = 0;
113
+ _Iter_peek.set(this, void 0);
95
114
  }
96
115
  peek() {
97
- return this.tokens[this.index];
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");
98
121
  }
99
122
  tryConsume(type) {
100
123
  const token = this.peek();
101
124
  if (token.type !== type)
102
125
  return;
103
- this.index++;
126
+ __classPrivateFieldSet(this, _Iter_peek, undefined, "f"); // Reset after consumed.
104
127
  return token.value;
105
128
  }
106
129
  consume(type) {
@@ -118,17 +141,14 @@ class Iter {
118
141
  }
119
142
  return result;
120
143
  }
121
- modifier() {
122
- return this.tryConsume("?") || this.tryConsume("*") || this.tryConsume("+");
123
- }
124
144
  }
145
+ _Iter_peek = new WeakMap();
125
146
  /**
126
- * Tokenized path instance. Can we passed around instead of string.
147
+ * Tokenized path instance.
127
148
  */
128
149
  class TokenData {
129
- constructor(tokens, delimiter) {
150
+ constructor(tokens) {
130
151
  this.tokens = tokens;
131
- this.delimiter = delimiter;
132
152
  }
133
153
  }
134
154
  exports.TokenData = TokenData;
@@ -136,177 +156,154 @@ exports.TokenData = TokenData;
136
156
  * Parse a string for the raw tokens.
137
157
  */
138
158
  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");
149
- if (name || pattern) {
150
- tokens.push({
151
- name: name || String(key++),
152
- pattern,
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}`);
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;
157
174
  }
158
- continue;
159
- }
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
- });
168
- continue;
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;
169
193
  }
170
- const open = it.tryConsume("{");
171
- if (open) {
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,
186
- });
187
- 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(", ")}`);
188
208
  }
189
- it.consume("END");
190
- break;
191
- } while (true);
192
- return new TokenData(tokens, delimiter);
209
+ return path;
210
+ };
193
211
  }
194
212
  /**
195
213
  * Compile a string to a template function for the path.
196
214
  */
197
215
  function compile(path, options = {}) {
198
- const data = path instanceof TokenData ? path : parse(path, options);
199
- return compileTokens(data, options);
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
+ };
200
229
  }
201
230
  /**
202
231
  * Convert a single token into a path building function.
203
232
  */
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`);
216
- }
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`);
222
- }
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
- };
234
- }
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);
235
238
  return (data) => {
236
- const value = data[token.name];
237
- return compile(value);
239
+ const [value, ...missing] = fn(data);
240
+ if (!missing.length)
241
+ return [value];
242
+ return [""];
238
243
  };
239
244
  }
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) {
245
+ const encodeValue = encode || NOOP_VALUE;
246
+ if (token.type === "wildcard" && encode !== false) {
247
247
  return (data) => {
248
248
  const value = data[token.name];
249
249
  if (value == null)
250
- return "";
251
- return stringify(value);
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
+ ];
252
264
  };
253
265
  }
254
266
  return (data) => {
255
267
  const value = data[token.name];
256
- return stringify(value);
257
- };
258
- }
259
- /**
260
- * Transform tokens into a path building function.
261
- */
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;
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)];
286
274
  };
287
275
  }
288
276
  /**
289
277
  * Create path match function from `path-to-regexp` spec.
290
278
  */
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);
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 = [];
295
283
  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);
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);
302
288
  }
303
- return decode || NOOP_VALUE;
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);
304
301
  });
305
- return function match(input) {
302
+ return Object.assign(function match(input) {
306
303
  const m = re.exec(input);
307
304
  if (!m)
308
305
  return false;
309
- const { 0: path, index } = m;
306
+ const { 0: path } = m;
310
307
  const params = Object.create(null);
311
308
  for (let i = 1; i < m.length; i++) {
312
309
  if (m[i] === undefined)
@@ -315,117 +312,71 @@ function match(path, options = {}) {
315
312
  const decoder = decoders[i - 1];
316
313
  params[key.name] = decoder(m[i]);
317
314
  }
318
- return { path, index, params };
319
- };
315
+ return { path, params };
316
+ }, { re });
320
317
  }
321
- /**
322
- * Escape a regular expression string.
323
- */
324
- function escape(str) {
325
- return str.replace(/([.+*?^${}()[\]|/\\])/g, "\\$1");
326
- }
327
- /**
328
- * Escape and repeat loose characters for regular expressions.
329
- */
330
- function looseReplacer(value, loose) {
331
- const escaped = escape(value);
332
- return loose ? `(?:${escaped})+(?!${escaped})` : escaped;
333
- }
334
- /**
335
- * Encode all non-delimiter characters using the encode function.
336
- */
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);
342
- }
343
- /**
344
- * Get the flags for a regexp from the options.
345
- */
346
- function toFlags(options) {
347
- 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);
348
322
  }
349
323
  /**
350
- * Expose a function for taking tokens and returning a RegExp.
324
+ * Generate a flat list of sequence tokens from the given tokens.
351
325
  */
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);
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);
335
+ }
336
+ }
337
+ else {
338
+ init.push(token);
339
+ }
340
+ yield* flatten(tokens, index + 1, init);
363
341
  }
364
342
  /**
365
- * Convert a token into a regexp string (re-used for path validation).
343
+ * Transform a flat sequence of tokens into a regular expression.
366
344
  */
367
- function toRegExpSource(data, stringify, keys, flags, strict) {
368
- const defaultPattern = `(?:(?!${escape(data.delimiter)}).)+?`;
345
+ function sequenceToRegExp(tokens, delimiter, keys) {
346
+ let result = "";
369
347
  let backtrack = "";
370
- let safe = true;
371
- return data.tokens.map((token, index) => {
372
- if (typeof token === "string") {
373
- backtrack = token;
374
- return stringify(token);
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;
375
356
  }
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}`);
357
+ if (token.type === "param" || token.type === "wildcard") {
358
+ if (!isSafeSegmentParam && !backtrack) {
359
+ throw new TypeError(`Missing text after "${token.name}": ${DEBUG_URL}`);
385
360
  }
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}`);
394
- }
395
- safe || (safe = !strict || safePattern(re, separator));
396
- if (!safe) {
397
- throw new TypeError(`Ambiguous pattern for "${token.name}" separator: ${DEBUG_URL}`);
398
- }
399
- safe = !strict;
400
- return `(?:${pre}(${pattern}(?:${sep}${pattern})*)${post})${mod}`;
361
+ if (token.type === "param") {
362
+ result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
401
363
  }
402
- return `(?:${pre}(${pattern})${post})${modifier}`;
364
+ else {
365
+ result += `(.+)`;
366
+ }
367
+ keys.push(token);
368
+ backtrack = "";
369
+ isSafeSegmentParam = false;
370
+ continue;
403
371
  }
404
- return `(?:${pre}${post})${modifier}`;
405
- });
406
- }
407
- function checkPattern(pattern, name, flags) {
408
- try {
409
- return new RegExp(`^${pattern}$`, flags);
410
- }
411
- catch (err) {
412
- throw new TypeError(`Invalid pattern for "${name}": ${err.message}`);
413
372
  }
373
+ return result;
414
374
  }
415
- function safePattern(re, value) {
416
- return value ? !re.test(value) : false;
417
- }
418
- /**
419
- * Normalize the given path string, returning a regular expression.
420
- *
421
- * An empty array can be passed in for the keys, which will hold the
422
- * placeholder key descriptions. For example, using `/user/:id`, `keys` will
423
- * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
424
- */
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 });
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("|")}).)`;
430
381
  }
431
382
  //# sourceMappingURL=index.js.map