@@ -21,11 +21,7 @@ export interface ParseOptions {
21
21
encodePath ?: Encode ;
22
22
}
23
23
24
- export interface MatchOptions {
25
- /**
26
- * Function for decoding strings for params, or `false` to disable entirely. (default: `decodeURIComponent`)
27
- */
28
- decode ?: Decode | false ;
24
+ export interface PathToRegexpOptions {
29
25
/**
30
26
* Matches the path completely without trailing characters. (default: `true`)
31
27
*/
@@ -44,6 +40,13 @@ export interface MatchOptions {
44
40
delimiter ?: string ;
45
41
}
46
42
43
+ export interface MatchOptions extends PathToRegexpOptions {
44
+ /**
45
+ * Function for decoding strings for params, or `false` to disable entirely. (default: `decodeURIComponent`)
46
+ */
47
+ decode ?: Decode | false ;
48
+ }
49
+
47
50
export interface CompileOptions {
48
51
/**
49
52
* Function for encoding input strings for output into the path, or `false` to disable entirely. (default: `encodeURIComponent`)
@@ -109,13 +112,6 @@ function escape(str: string) {
109
112
return str . replace ( / [ . + * ? ^ $ { } ( ) [ \] | / \\ ] / g, "\\$&" ) ;
110
113
}
111
114
112
- /**
113
- * Get the flags for a regexp from the options.
114
- */
115
- function toFlags ( options : { sensitive ?: boolean } ) {
116
- return options . sensitive ? "s" : "is" ;
117
- }
118
-
119
115
/**
120
116
* Tokenize input string.
121
117
*/
@@ -253,6 +249,16 @@ export interface Group {
253
249
tokens : Token [ ] ;
254
250
}
255
251
252
+ /**
253
+ * A token that corresponds with a regexp capture.
254
+ */
255
+ export type Key = Parameter | Wildcard ;
256
+
257
+ /**
258
+ * A sequence of `path-to-regexp` keys that match capturing groups.
259
+ */
260
+ export type Keys = Array < Key > ;
261
+
256
262
/**
257
263
* A sequence of path match characters.
258
264
*/
@@ -316,14 +322,15 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
316
322
}
317
323
318
324
/**
319
- * Transform tokens into a path building function.
325
+ * Compile a string to a template function for the path .
320
326
*/
321
- function $ compile< P extends ParamData > (
322
- data : TokenData ,
323
- options : CompileOptions ,
324
- ) : PathFunction < P > {
327
+ export function compile < P extends ParamData = ParamData > (
328
+ path : Path ,
329
+ options : CompileOptions & ParseOptions = { } ,
330
+ ) {
325
331
const { encode = encodeURIComponent , delimiter = DEFAULT_DELIMITER } =
326
332
options ;
333
+ const data = path instanceof TokenData ? path : parse ( path , options ) ;
327
334
const fn = tokensToFunction ( data . tokens , delimiter , encode ) ;
328
335
329
336
return function path ( data : P = { } as P ) {
@@ -335,19 +342,6 @@ function $compile<P extends ParamData>(
335
342
} ;
336
343
}
337
344
338
- /**
339
- * Compile a string to a template function for the path.
340
- */
341
- export function compile < P extends ParamData = ParamData > (
342
- path : Path ,
343
- options : CompileOptions & ParseOptions = { } ,
344
- ) {
345
- return $compile < P > (
346
- path instanceof TokenData ? path : parse ( path , options ) ,
347
- options ,
348
- ) ;
349
- }
350
-
351
345
export type ParamData = Partial < Record < string , string | string [ ] > > ;
352
346
export type PathFunction < P extends ParamData > = ( data ?: P ) => string ;
353
347
@@ -451,75 +445,77 @@ export type Match<P extends ParamData> = false | MatchResult<P>;
451
445
export type MatchFunction < P extends ParamData > = ( path : string ) => Match < P > ;
452
446
453
447
/**
454
- * Create path match function from `path-to-regexp` spec .
448
+ * Supported path types .
455
449
*/
456
- function $match < P extends ParamData > (
457
- data : TokenData [ ] ,
458
- options : MatchOptions = { } ,
459
- ) : MatchFunction < P > {
460
- const {
461
- decode = decodeURIComponent ,
462
- delimiter = DEFAULT_DELIMITER ,
463
- end = true ,
464
- trailing = true ,
465
- } = options ;
466
- const flags = toFlags ( options ) ;
467
- const sources : string [ ] = [ ] ;
468
- const keys : Array < Parameter | Wildcard > = [ ] ;
469
-
470
- for ( const { tokens } of data ) {
471
- for ( const seq of flatten ( tokens , 0 , [ ] ) ) {
472
- const regexp = sequenceToRegExp ( seq , delimiter , keys ) ;
473
- sources . push ( regexp ) ;
474
- }
475
- }
476
-
477
- let pattern = `^(?:${ sources . join ( "|" ) } )` ;
478
- if ( trailing ) pattern += `(?:${ escape ( delimiter ) } $)?` ;
479
- pattern += end ? "$" : `(?=${ escape ( delimiter ) } |$)` ;
450
+ export type Path = string | TokenData ;
480
451
481
- const re = new RegExp ( pattern , flags ) ;
452
+ /**
453
+ * Transform a path into a match function.
454
+ */
455
+ export function match < P extends ParamData > (
456
+ path : Path | Path [ ] ,
457
+ options : MatchOptions & ParseOptions = { } ,
458
+ ) : MatchFunction < P > {
459
+ const { decode = decodeURIComponent , delimiter = DEFAULT_DELIMITER } =
460
+ options ;
461
+ const { regexp, keys } = pathToRegexp ( path , options ) ;
482
462
483
463
const decoders = keys . map ( ( key ) => {
484
464
if ( decode === false ) return NOOP_VALUE ;
485
465
if ( key . type === "param" ) return decode ;
486
466
return ( value : string ) => value . split ( delimiter ) . map ( decode ) ;
487
467
} ) ;
488
468
489
- return Object . assign (
490
- function match ( input : string ) {
491
- const m = re . exec ( input ) ;
492
- if ( ! m ) return false ;
469
+ return function match ( input : string ) {
470
+ const m = regexp . exec ( input ) ;
471
+ if ( ! m ) return false ;
493
472
494
- const { 0 : path } = m ;
495
- const params = Object . create ( null ) ;
473
+ const path = m [ 0 ] ;
474
+ const params = Object . create ( null ) ;
496
475
497
- for ( let i = 1 ; i < m . length ; i ++ ) {
498
- if ( m [ i ] === undefined ) continue ;
476
+ for ( let i = 1 ; i < m . length ; i ++ ) {
477
+ if ( m [ i ] === undefined ) continue ;
499
478
500
- const key = keys [ i - 1 ] ;
501
- const decoder = decoders [ i - 1 ] ;
502
- params [ key . name ] = decoder ( m [ i ] ) ;
503
- }
479
+ const key = keys [ i - 1 ] ;
480
+ const decoder = decoders [ i - 1 ] ;
481
+ params [ key . name ] = decoder ( m [ i ] ) ;
482
+ }
504
483
505
- return { path, params } ;
506
- } ,
507
- { re } ,
508
- ) ;
484
+ return { path, params } ;
485
+ } ;
509
486
}
510
487
511
- export type Path = string | TokenData ;
512
-
513
- export function match < P extends ParamData > (
488
+ export function pathToRegexp (
514
489
path : Path | Path [ ] ,
515
- options : MatchOptions & ParseOptions = { } ,
516
- ) : MatchFunction < P > {
490
+ options : PathToRegexpOptions & ParseOptions = { } ,
491
+ ) {
492
+ const {
493
+ delimiter = DEFAULT_DELIMITER ,
494
+ end = true ,
495
+ sensitive = false ,
496
+ trailing = true ,
497
+ } = options ;
498
+ const keys : Keys = [ ] ;
499
+ const sources : string [ ] = [ ] ;
500
+ const flags = sensitive ? "s" : "is" ;
517
501
const paths = Array . isArray ( path ) ? path : [ path ] ;
518
502
const items = paths . map ( ( path ) =>
519
503
path instanceof TokenData ? path : parse ( path , options ) ,
520
504
) ;
521
505
522
- return $match ( items , options ) ;
506
+ for ( const { tokens } of items ) {
507
+ for ( const seq of flatten ( tokens , 0 , [ ] ) ) {
508
+ const regexp = sequenceToRegExp ( seq , delimiter , keys ) ;
509
+ sources . push ( regexp ) ;
510
+ }
511
+ }
512
+
513
+ let pattern = `^(?:${ sources . join ( "|" ) } )` ;
514
+ if ( trailing ) pattern += `(?:${ escape ( delimiter ) } $)?` ;
515
+ pattern += end ? "$" : `(?=${ escape ( delimiter ) } |$)` ;
516
+
517
+ const regexp = new RegExp ( pattern , flags ) ;
518
+ return { regexp, keys } ;
523
519
}
524
520
525
521
/**
@@ -556,11 +552,7 @@ function* flatten(
556
552
/**
557
553
* Transform a flat sequence of tokens into a regular expression.
558
554
*/
559
- function sequenceToRegExp (
560
- tokens : Flattened [ ] ,
561
- delimiter : string ,
562
- keys : Array < Parameter | Wildcard > ,
563
- ) : string {
555
+ function sequenceToRegExp ( tokens : Flattened [ ] , delimiter : string , keys : Keys ) {
564
556
let result = "" ;
565
557
let backtrack = "" ;
566
558
let isSafeSegmentParam = true ;
0 commit comments