@@ -333,8 +333,8 @@ export function compile<P extends ParamData = ParamData>(
333333 const data = path instanceof TokenData ? path : parse ( path , options ) ;
334334 const fn = tokensToFunction ( data . tokens , delimiter , encode ) ;
335335
336- return function path ( data : P = { } as P ) {
337- const [ path , ...missing ] = fn ( data ) ;
336+ return function path ( params : P = { } as P ) {
337+ const [ path , ...missing ] = fn ( params ) ;
338338 if ( missing . length ) {
339339 throw new TypeError ( `Missing parameters: ${ missing . join ( ", " ) } ` ) ;
340340 }
@@ -498,16 +498,9 @@ export function pathToRegexp(
498498 const keys : Keys = [ ] ;
499499 const sources : string [ ] = [ ] ;
500500 const flags = sensitive ? "" : "i" ;
501- const paths = Array . isArray ( path ) ? path : [ path ] ;
502- const items = paths . map ( ( path ) =>
503- path instanceof TokenData ? path : parse ( path , options ) ,
504- ) ;
505501
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- }
502+ for ( const seq of flat ( path , options ) ) {
503+ sources . push ( toRegExp ( seq , delimiter , keys ) ) ;
511504 }
512505
513506 let pattern = `^(?:${ sources . join ( "|" ) } )` ;
@@ -523,6 +516,22 @@ export function pathToRegexp(
523516 */
524517type Flattened = Text | Parameter | Wildcard ;
525518
519+ /**
520+ * Path or array of paths to normalize.
521+ */
522+ function * flat (
523+ path : Path | Path [ ] ,
524+ options : ParseOptions ,
525+ ) : Generator < Flattened [ ] > {
526+ if ( Array . isArray ( path ) ) {
527+ for ( const p of path ) yield * flat ( p , options ) ;
528+ return ;
529+ }
530+
531+ const data = path instanceof TokenData ? path : parse ( path , options ) ;
532+ yield * flatten ( data . tokens , 0 , [ ] ) ;
533+ }
534+
526535/**
527536 * Generate a flat list of sequence tokens from the given tokens.
528537 */
@@ -538,8 +547,7 @@ function* flatten(
538547 const token = tokens [ index ] ;
539548
540549 if ( token . type === "group" ) {
541- const fork = init . slice ( ) ;
542- for ( const seq of flatten ( token . tokens , 0 , fork ) ) {
550+ for ( const seq of flatten ( token . tokens , 0 , init . slice ( ) ) ) {
543551 yield * flatten ( tokens , index + 1 , seq ) ;
544552 }
545553 } else {
@@ -552,14 +560,12 @@ function* flatten(
552560/**
553561 * Transform a flat sequence of tokens into a regular expression.
554562 */
555- function sequenceToRegExp ( tokens : Flattened [ ] , delimiter : string , keys : Keys ) {
563+ function toRegExp ( tokens : Flattened [ ] , delimiter : string , keys : Keys ) {
556564 let result = "" ;
557565 let backtrack = "" ;
558566 let isSafeSegmentParam = true ;
559567
560- for ( let i = 0 ; i < tokens . length ; i ++ ) {
561- const token = tokens [ i ] ;
562-
568+ for ( const token of tokens ) {
563569 if ( token . type === "text" ) {
564570 result += escape ( token . value ) ;
565571 backtrack += token . value ;
@@ -588,6 +594,9 @@ function sequenceToRegExp(tokens: Flattened[], delimiter: string, keys: Keys) {
588594 return result ;
589595}
590596
597+ /**
598+ * Block backtracking on previous text and ignore delimiter string.
599+ */
591600function negate ( delimiter : string , backtrack : string ) {
592601 if ( backtrack . length < 2 ) {
593602 if ( delimiter . length < 2 ) return `[^${ escape ( delimiter + backtrack ) } ]` ;
@@ -621,12 +630,18 @@ export function stringify(data: TokenData) {
621630 . join ( "" ) ;
622631}
623632
633+ /**
634+ * Validate the parameter name contains valid ID characters.
635+ */
624636function isNameSafe ( name : string ) {
625637 const [ first , ...rest ] = name ;
626638 if ( ! ID_START . test ( first ) ) return false ;
627639 return rest . every ( ( char ) => ID_CONTINUE . test ( char ) ) ;
628640}
629641
642+ /**
643+ * Validate the next token does not interfere with the current param name.
644+ */
630645function isNextNameSafe ( token : Token | undefined ) {
631646 if ( ! token || token . type !== "text" ) return true ;
632647 return ! ID_CONTINUE . test ( token . value [ 0 ] ) ;
0 commit comments