@@ -44,56 +44,91 @@ export function init(blocks: Block[]) {
4444 inited = true ;
4545}
4646
47+ const CURRENT_SECTION_BOOST = 2 ;
48+ const EXACT_MATCH_BOOST = 10 ;
49+ const WORD_MATCH_BOOST = 4 ;
50+ const NEAR_MATCH_BOOST = 2 ;
51+ const BREADCRUMB_LENGTH_BOOST = 0.2 ;
52+
53+ interface Entry {
54+ block : Block ;
55+ score : number ;
56+ rank : number ;
57+ }
58+
4759/**
4860 * Search for a given query in the existing index
4961 */
50- export function search ( query : string ) : BlockGroup [ ] {
62+ export function search ( query : string , path : string ) : BlockGroup [ ] {
5163 const escaped = query . replace ( / [ - [ \] { } ( ) * + ? . , \\ ^ $ | # \s ] / g, '\\$&' ) ;
52- const regex = new RegExp ( `(^|\\b)${ escaped } ` , 'i' ) ;
64+ const exact_match = new RegExp ( `^${ escaped } $` , 'i' ) ;
65+ const word_match = new RegExp ( `(^|\\b)${ escaped } ($|\\b)` , 'i' ) ;
66+ const near_match = new RegExp ( `(^|\\b)${ escaped } ` , 'i' ) ;
67+
68+ const parts = path . split ( '/' ) ;
5369
5470 const blocks = indexes
5571 . flatMap ( ( index ) => index . search ( query ) )
5672 // @ts -expect-error flexsearch types are wrong i think?
5773 . map ( lookup )
58- . map ( ( block , rank ) => ( { block : block as Block , rank } ) )
59- . sort ( ( a , b ) => {
60- // If rank is way lower, give that priority
61- if ( Math . abs ( a . rank - b . rank ) > 3 ) {
62- return a . rank - b . rank ;
74+ . map ( ( block , rank ) => {
75+ const block_parts = block . href . split ( '/' ) ;
76+
77+ // prioritise current section
78+ let score = block_parts . findIndex ( ( part , i ) => part !== parts [ i ] ) ;
79+ if ( score === - 1 ) score = block_parts . length ;
80+ score *= CURRENT_SECTION_BOOST ;
81+
82+ if ( block . breadcrumbs . some ( ( text ) => exact_match . test ( text ) ) ) {
83+ console . log ( 'EXACT MATCH' , block . breadcrumbs ) ;
84+ score += EXACT_MATCH_BOOST ;
85+ } else if ( block . breadcrumbs . some ( ( text ) => word_match . test ( text ) ) ) {
86+ score += WORD_MATCH_BOOST ;
87+ } else if ( block . breadcrumbs . some ( ( text ) => near_match . test ( text ) ) ) {
88+ score += NEAR_MATCH_BOOST ;
6389 }
6490
65- const a_title_matches = regex . test ( a . block . breadcrumbs . at ( - 1 ) ! ) ;
66- const b_title_matches = regex . test ( b . block . breadcrumbs . at ( - 1 ) ! ) ;
91+ // prioritise branches over leaves
92+ score -= block . breadcrumbs . length * BREADCRUMB_LENGTH_BOOST ;
6793
68- // massage the order a bit, so that title matches
69- // are given higher priority
70- if ( a_title_matches !== b_title_matches ) {
71- return a_title_matches ? - 1 : 1 ;
72- }
94+ const entry : Entry = { block, score, rank } ;
7395
74- return a . block . breadcrumbs . length - b . block . breadcrumbs . length || a . rank - b . rank ;
75- } )
76- . map ( ( { block } ) => block ) ;
96+ return entry ;
97+ } ) ;
7798
78- const groups : Record < string , BlockGroup > = { } ;
99+ const grouped : Record < string , { breadcrumbs : string [ ] ; entries : Entry [ ] } > = { } ;
79100
80- for ( const block of blocks ) {
81- const breadcrumbs = block . breadcrumbs . slice ( 0 , 2 ) ;
82-
83- const group = ( groups [ breadcrumbs . join ( '::' ) ] ??= {
101+ for ( const entry of blocks ) {
102+ const breadcrumbs = entry . block . breadcrumbs . slice ( 0 , 2 ) ;
103+ const group = ( grouped [ breadcrumbs . join ( '::' ) ] ??= {
84104 breadcrumbs,
85- blocks : [ ]
105+ entries : [ ]
86106 } ) ;
87107
88- group . blocks . push ( block ) ;
108+ group . entries . push ( entry ) ;
89109 }
90110
91- return Object . values ( groups ) ;
111+ const sorted = Object . values ( grouped ) ;
112+
113+ // sort blocks within groups...
114+ for ( const group of sorted ) {
115+ group . entries . sort ( ( a , b ) => b . score - a . score || a . rank - b . rank ) ;
116+ }
117+
118+ // ...then sort groups
119+ sorted . sort ( ( a , b ) => b . entries [ 0 ] . score - a . entries [ 0 ] . score ) ;
120+
121+ return sorted . map ( ( group ) => {
122+ return {
123+ breadcrumbs : group . breadcrumbs ,
124+ blocks : group . entries . map ( ( entry ) => entry . block )
125+ } ;
126+ } ) ;
92127}
93128
94129/**
95130 * Get a block with details by its href
96131 */
97132export function lookup ( href : string ) {
98- return map . get ( href ) ;
133+ return map . get ( href ) ! ;
99134}
0 commit comments