@@ -190,7 +190,7 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
190190 } else {
191191 const next = createOptionalNode ( value , caseSensitive , prefix , suffix )
192192 nextNode = next
193- nextNode . parent = node
193+ next . parent = node
194194 node . optional ??= [ ]
195195 node . optional . push ( next )
196196 }
@@ -204,9 +204,8 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
204204 const next = createWildcardNode ( caseSensitive , prefix , suffix )
205205 nextNode = next
206206 next . parent = node
207- next . routeId = route . id
208- node . wildcard = next
209- return
207+ node . wildcard ??= [ ]
208+ node . wildcard . push ( next )
210209 }
211210 }
212211 node = nextNode
@@ -341,8 +340,8 @@ type SegmentNode = {
341340 // Optional dynamic segments ({-$param})
342341 optional : Array < OptionalSegmentNode > | null
343342
344- // Wildcard segment ($ - lowest priority)
345- wildcard : WildcardSegmentNode | null
343+ // Wildcard segments ($ - lowest priority)
344+ wildcard : Array < WildcardSegmentNode > | null
346345
347346 // Terminal route (if this path can end here)
348347 routeId : string | null
@@ -462,6 +461,8 @@ function getNodeMatch(parts: Array<string>, segmentTree: SegmentNode) {
462461 { node : segmentTree , partIndex : 0 }
463462 ]
464463
464+ let wildcardMatch : typeof stack [ 0 ] | null = null
465+
465466 while ( stack . length ) {
466467 let { node, partIndex, skipped } = stack . shift ( ) !
467468
@@ -529,25 +530,31 @@ function getNodeMatch(parts: Array<string>, segmentTree: SegmentNode) {
529530
530531 // 5. Try wildcard match
531532 if ( node . wildcard ) {
532- const { prefix, suffix } = node . wildcard
533- if ( prefix ) {
534- const casePart = node . wildcard . caseSensitive ? part : part . toLowerCase ( )
535- if ( ! casePart . startsWith ( prefix ) ) break
536- }
537- if ( suffix ) {
538- const part = parts [ parts . length - 1 ] !
539- const casePart = node . wildcard . caseSensitive ? part : part . toLowerCase ( )
540- if ( ! casePart . endsWith ( suffix ) ) break
533+ for ( const segment of node . wildcard ) {
534+ const { prefix, suffix } = segment
535+ if ( prefix ) {
536+ const casePart = segment . caseSensitive ? part : part . toLowerCase ( )
537+ if ( ! casePart . startsWith ( prefix ) ) continue
538+ }
539+ if ( suffix ) {
540+ const part = parts [ parts . length - 1 ] !
541+ const casePart = segment . caseSensitive ? part : part . toLowerCase ( )
542+ if ( ! casePart . endsWith ( suffix ) ) continue
543+ }
544+ // a wildcard match terminates the loop, but we need to continue searching in case there's a longer match
545+ if ( ! wildcardMatch || ( wildcardMatch . partIndex < partIndex ) ) {
546+ wildcardMatch = { node : segment , partIndex, skipped }
547+ }
548+ break main
541549 }
542- partIndex = parts . length
543- node = node . wildcard
544- continue
545550 }
546551
547552 // No match found
548553 break
549554 }
550555 }
551556
557+ if ( wildcardMatch ) return wildcardMatch
558+
552559 return null
553560}
0 commit comments