@@ -11,9 +11,11 @@ import {
1111} from './utils'
1212import { processRouteTree } from './process-route-tree'
1313import {
14+ SEGMENT_TYPE_PATHNAME ,
1415 cleanPath ,
1516 interpolatePath ,
1617 matchPathname ,
18+ parsePathname ,
1719 resolvePath ,
1820 trimPath ,
1921 trimPathRight ,
@@ -31,7 +33,7 @@ import {
3133 executeRewriteOutput ,
3234 rewriteBasepath ,
3335} from './rewrite'
34- import type { ParsePathnameCache } from './path'
36+ import type { ParsePathnameCache , Segment } from './path'
3537import type { SearchParser , SearchSerializer } from './searchParams'
3638import type { AnyRedirect , ResolvedRedirect } from './redirect'
3739import type {
@@ -2686,26 +2688,54 @@ export function getMatchedRoutes<TRouteLike extends RouteLike>({
26862688 let fuzzyMatch :
26872689 | { foundRoute : TRouteLike ; routeParams : Record < string , string > }
26882690 | undefined = undefined
2691+ const exactMatches : Array < {
2692+ route : TRouteLike
2693+ routeParams : Record < string , string >
2694+ endsWithStatic : boolean
2695+ } > = [ ]
2696+
2697+ const getLastNonSlashSegment = ( segments : ReadonlyArray < Segment > ) => {
2698+ for ( let i = segments . length - 1 ; i >= 0 ; i -- ) {
2699+ if ( segments [ i ] ?. value !== '/' ) return segments [ i ]
2700+ }
2701+ return undefined
2702+ }
2703+
26892704 for ( const route of flatRoutes ) {
26902705 const matchedParams = getMatchedParams ( route )
26912706
26922707 if ( matchedParams ) {
2693- if (
2694- route . path !== '/' &&
2695- ( matchedParams as Record < string , string > ) [ '**' ]
2696- ) {
2697- if ( ! fuzzyMatch ) {
2698- fuzzyMatch = { foundRoute : route , routeParams : matchedParams }
2699- }
2708+ const isFuzzy =
2709+ route . path !== '/' && ( matchedParams as Record < string , string > ) [ '**' ]
2710+
2711+ if ( isFuzzy ) {
2712+ fuzzyMatch ??= { foundRoute : route , routeParams : matchedParams }
27002713 } else {
2701- foundRoute = route
2702- routeParams = matchedParams
2703- break
2714+ const routeSegments = parsePathname ( route . fullPath , parseCache )
2715+ const pathSegments = parsePathname ( trimmedPath , parseCache )
2716+ const lastRouteSegment = getLastNonSlashSegment ( routeSegments )
2717+ const lastPathSegment = getLastNonSlashSegment ( pathSegments )
2718+ const endsWithStatic =
2719+ lastRouteSegment ?. type === SEGMENT_TYPE_PATHNAME &&
2720+ lastPathSegment ?. type === SEGMENT_TYPE_PATHNAME &&
2721+ lastRouteSegment . value === lastPathSegment . value
2722+
2723+ exactMatches . push ( {
2724+ route,
2725+ routeParams : matchedParams ,
2726+ endsWithStatic : ! ! endsWithStatic ,
2727+ } )
27042728 }
27052729 }
27062730 }
2707- // did not find a perfect fit, so take the fuzzy matching route if it exists
2708- if ( ! foundRoute && fuzzyMatch ) {
2731+
2732+ if ( exactMatches . length > 0 ) {
2733+ exactMatches . sort (
2734+ ( a , b ) => Number ( b . endsWithStatic ) - Number ( a . endsWithStatic ) ,
2735+ )
2736+ foundRoute = exactMatches [ 0 ] ! . route
2737+ routeParams = exactMatches [ 0 ] ! . routeParams
2738+ } else if ( fuzzyMatch ) {
27092739 foundRoute = fuzzyMatch . foundRoute
27102740 routeParams = fuzzyMatch . routeParams
27112741 }
0 commit comments