@@ -136,18 +136,25 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
136136 const value = path . substring ( data [ 2 ] ! , data [ 3 ] )
137137 switch ( kind ) {
138138 case SEGMENT_TYPE_PATHNAME : {
139- const name = caseSensitive ? value : value . toLowerCase ( )
140- const existingNode = node . static ?. find ( s => s . caseSensitive === caseSensitive && s . name === name )
141- if ( existingNode ) {
142- nextNode = existingNode . node
139+ if ( caseSensitive ) {
140+ const existingNode = node . static ?. get ( value )
141+ if ( existingNode ) {
142+ nextNode = existingNode
143+ } else {
144+ node . static ??= new Map ( )
145+ nextNode = { }
146+ node . static . set ( value , nextNode )
147+ }
143148 } else {
144- node . static ??= [ ]
145- nextNode = { }
146- node . static . push ( {
147- name,
148- caseSensitive,
149- node : nextNode
150- } )
149+ const name = value . toLowerCase ( )
150+ const existingNode = node . staticInsensitive ?. get ( name )
151+ if ( existingNode ) {
152+ nextNode = existingNode
153+ } else {
154+ node . staticInsensitive ??= new Map ( )
155+ nextNode = { }
156+ node . staticInsensitive . set ( name , nextNode )
157+ }
151158 }
152159 break
153160 }
@@ -217,21 +224,27 @@ function parseSegments<TRouteLike extends RouteLike>(data: Uint16Array, route: T
217224 }
218225}
219226
220- function sortStaticSegments ( a : NonNullable < SegmentNode [ 'static' ] > [ number ] , b : NonNullable < SegmentNode [ 'static' ] > [ number ] ) {
221- if ( a . caseSensitive && ! b . caseSensitive ) return - 1
222- if ( ! a . caseSensitive && b . caseSensitive ) return 1
223- return b . name . length - a . name . length
227+ function sortDynamic ( a : { prefix ?: string , suffix ?: string } , b : { prefix ?: string , suffix ?: string } ) {
228+ const aScore =
229+ // bonus for having both prefix and suffix
230+ ( a . prefix && a . suffix ? 500 : 0 )
231+ // prefix counts double
232+ + ( a . prefix ? a . prefix . length * 2 : 0 )
233+ // suffix counts single
234+ + ( a . suffix ? a . suffix . length : 0 )
235+ const bScore =
236+ // bonus for having both prefix and suffix
237+ ( b . prefix && b . suffix ? 500 : 0 )
238+ // prefix counts double
239+ + ( b . prefix ? b . prefix . length * 2 : 0 )
240+ // suffix counts single
241+ + ( b . suffix ? b . suffix . length : 0 )
242+ return bScore - aScore
224243}
225244
226245function sortTreeNodes ( node : SegmentNode ) {
227- if ( node . static ?. length ) {
228- node . static . sort ( sortStaticSegments )
229- for ( const child of node . static ) {
230- sortTreeNodes ( child . node )
231- }
232- }
233246 if ( node . dynamic ?. length ) {
234- node . dynamic . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) // TODO
247+ node . dynamic . sort ( sortDynamic )
235248 for ( const child of node . dynamic ) {
236249 sortTreeNodes ( child . node )
237250 }
@@ -247,12 +260,10 @@ function sortTreeNodes(node: SegmentNode) {
247260
248261type SegmentNode = {
249262 // Static segments (highest priority)
250- // TODO: maybe we could split this into two maps: caseSensitive and caseInsensitive for faster lookup
251- static ?: Array < {
252- name : string
253- caseSensitive : boolean
254- node : SegmentNode
255- } >
263+ static ?: Map < string , SegmentNode >
264+
265+ // Case insensitive static segments (second highest priority)
266+ staticInsensitive ?: Map < string , SegmentNode >
256267
257268 // Dynamic segments ($param)
258269 dynamic ?: Array < {
0 commit comments