@@ -297,7 +297,7 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
297297 if ( asterisk ) {
298298 tokens . push ( {
299299 name : String ( key ++ ) ,
300- pattern : `${ negate ( escape ( delimiter ) ) } *` ,
300+ pattern : `${ negate ( delimiter ) } *` ,
301301 modifier : "*" ,
302302 separator : delimiter ,
303303 } ) ;
@@ -590,7 +590,6 @@ function tokensToRegexp(data: TokenData, options: PathOptions) {
590590 * Convert a token into a regexp string (re-used for path validation).
591591 */
592592function toRegExpSource ( data : TokenData , keys : Key [ ] ) : string [ ] {
593- const delim = escape ( data . delimiter ) ;
594593 const sources = Array ( data . tokens . length ) ;
595594 let backtrack = "" ;
596595
@@ -600,7 +599,8 @@ function toRegExpSource(data: TokenData, keys: Key[]): string[] {
600599 const token = data . tokens [ i ] ;
601600
602601 if ( typeof token === "string" ) {
603- sources [ i ] = backtrack = escape ( token ) ;
602+ backtrack = token ;
603+ sources [ i ] = escape ( token ) ;
604604 continue ;
605605 }
606606
@@ -615,39 +615,65 @@ function toRegExpSource(data: TokenData, keys: Key[]): string[] {
615615 const post = escape ( suffix ) ;
616616
617617 if ( token . name ) {
618- let pattern = token . pattern || "" ;
619-
618+ backtrack = suffix || backtrack ;
620619 keys . unshift ( token ) ;
621620
622621 if ( isRepeat ( token ) ) {
623- const mod = modifier === "*" ? "?" : "" ;
624- const sep = escape ( separator ) ;
625-
626- if ( ! sep ) {
622+ if ( ! separator ) {
627623 throw new TypeError (
628624 `Missing separator for "${ token . name } ": ${ DEBUG_URL } ` ,
629625 ) ;
630626 }
631627
632- pattern ||= `${ negate ( delim , sep , post || backtrack ) } +` ;
633- sources [ i ] =
634- `(?:${ pre } ((?:${ pattern } )(?:${ sep } (?:${ pattern } ))*)${ post } )${ mod } ` ;
628+ const mod = modifier === "*" ? "?" : "" ;
629+ const sep = escape ( separator ) ;
630+ const pattern =
631+ token . pattern || `${ negate ( data . delimiter , separator , backtrack ) } +` ;
632+
633+ sources [ i ] = wrap (
634+ pre ,
635+ `(?:${ pattern } )(?:${ sep } (?:${ pattern } ))*` ,
636+ post ,
637+ mod ,
638+ ) ;
635639 } else {
636- pattern ||= `${ negate ( delim , post || backtrack ) } +` ;
637- sources [ i ] = `(?:${ pre } (${ pattern } )${ post } )${ modifier } ` ;
640+ sources [ i ] = wrap (
641+ pre ,
642+ token . pattern || `${ negate ( data . delimiter , backtrack ) } +` ,
643+ post ,
644+ modifier ,
645+ ) ;
638646 }
639647
640- backtrack = pre || pattern ;
648+ backtrack = prefix ;
641649 } else {
642650 sources [ i ] = `(?:${ pre } ${ post } )${ modifier } ` ;
643- backtrack = `${ pre } ${ post } ` ;
651+ backtrack = `${ prefix } ${ suffix } ` ;
644652 }
645653 }
646654
647655 return sources ;
648656}
649657
650658function negate ( ...args : string [ ] ) {
651- const values = Array . from ( new Set ( args ) ) . filter ( Boolean ) ;
652- return `(?:(?!${ values . join ( "|" ) } ).)` ;
659+ const values = args . sort ( ) . filter ( ( value , index , array ) => {
660+ for ( let i = 0 ; i < index ; i ++ ) {
661+ const v = array [ i ] ;
662+ if ( v . length && value . startsWith ( v ) ) return false ;
663+ }
664+ return value . length > 0 ;
665+ } ) ;
666+
667+ const isSimple = values . every ( ( value ) => value . length === 1 ) ;
668+ if ( isSimple ) return `[^${ escape ( values . join ( "" ) ) } ]` ;
669+
670+ return `(?:(?!${ values . map ( escape ) . join ( "|" ) } ).)` ;
671+ }
672+
673+ function wrap ( pre : string , pattern : string , post : string , modifier : string ) {
674+ if ( pre || post ) {
675+ return `(?:${ pre } (${ pattern } )${ post } )${ modifier } ` ;
676+ }
677+
678+ return `(${ pattern } )${ modifier } ` ;
653679}
0 commit comments