4
4
*
5
5
* Sphinx JavaScript utilities for the full-text search.
6
6
*
7
- * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS.
7
+ * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
8
8
* :license: BSD, see LICENSE for details.
9
9
*
10
10
*/
@@ -99,7 +99,7 @@ const _displayItem = (item, searchTerms, highlightTerms) => {
99
99
. then ( ( data ) => {
100
100
if ( data )
101
101
listItem . appendChild (
102
- Search . makeSearchSummary ( data , searchTerms , anchor )
102
+ Search . makeSearchSummary ( data , searchTerms )
103
103
) ;
104
104
// highlight search terms in the summary
105
105
if ( SPHINX_HIGHLIGHT_ENABLED ) // set in sphinx_highlight.js
@@ -116,8 +116,8 @@ const _finishSearch = (resultCount) => {
116
116
) ;
117
117
else
118
118
Search . status . innerText = _ (
119
- " Search finished, found ${resultCount} page(s) matching the search query."
120
- ) . replace ( '${resultCount}' , resultCount ) ;
119
+ ` Search finished, found ${ resultCount } page(s) matching the search query.`
120
+ ) ;
121
121
} ;
122
122
const _displayNextItem = (
123
123
results ,
@@ -137,22 +137,6 @@ const _displayNextItem = (
137
137
// search finished, update title and status message
138
138
else _finishSearch ( resultCount ) ;
139
139
} ;
140
- // Helper function used by query() to order search results.
141
- // Each input is an array of [docname, title, anchor, descr, score, filename].
142
- // Order the results by score (in opposite order of appearance, since the
143
- // `_displayNextItem` function uses pop() to retrieve items) and then alphabetically.
144
- const _orderResultsByScoreThenName = ( a , b ) => {
145
- const leftScore = a [ 4 ] ;
146
- const rightScore = b [ 4 ] ;
147
- if ( leftScore === rightScore ) {
148
- // same score: sort alphabetically
149
- const leftTitle = a [ 1 ] . toLowerCase ( ) ;
150
- const rightTitle = b [ 1 ] . toLowerCase ( ) ;
151
- if ( leftTitle === rightTitle ) return 0 ;
152
- return leftTitle > rightTitle ? - 1 : 1 ; // inverted is intentional
153
- }
154
- return leftScore > rightScore ? 1 : - 1 ;
155
- } ;
156
140
157
141
/**
158
142
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
@@ -176,26 +160,13 @@ const Search = {
176
160
_queued_query : null ,
177
161
_pulse_status : - 1 ,
178
162
179
- htmlToText : ( htmlString , anchor ) => {
163
+ htmlToText : ( htmlString ) => {
180
164
const htmlElement = new DOMParser ( ) . parseFromString ( htmlString , 'text/html' ) ;
181
- for ( const removalQuery of [ ".headerlinks" , "script" , "style" ] ) {
182
- htmlElement . querySelectorAll ( removalQuery ) . forEach ( ( el ) => { el . remove ( ) } ) ;
183
- }
184
- if ( anchor ) {
185
- const anchorContent = htmlElement . querySelector ( `[role="main"] ${ anchor } ` ) ;
186
- if ( anchorContent ) return anchorContent . textContent ;
187
-
188
- console . warn (
189
- `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${ anchor } '. Check your theme or template.`
190
- ) ;
191
- }
192
-
193
- // if anchor not specified or not found, fall back to main content
165
+ htmlElement . querySelectorAll ( ".headerlink" ) . forEach ( ( el ) => { el . remove ( ) } ) ;
194
166
const docContent = htmlElement . querySelector ( '[role="main"]' ) ;
195
- if ( docContent ) return docContent . textContent ;
196
-
167
+ if ( docContent !== undefined ) return docContent . textContent ;
197
168
console . warn (
198
- "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template."
169
+ "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
199
170
) ;
200
171
return "" ;
201
172
} ,
@@ -268,7 +239,16 @@ const Search = {
268
239
else Search . deferQuery ( query ) ;
269
240
} ,
270
241
271
- _parseQuery : ( query ) => {
242
+ /**
243
+ * execute search (requires search index to be loaded)
244
+ */
245
+ query : ( query ) => {
246
+ const filenames = Search . _index . filenames ;
247
+ const docNames = Search . _index . docnames ;
248
+ const titles = Search . _index . titles ;
249
+ const allTitles = Search . _index . alltitles ;
250
+ const indexEntries = Search . _index . indexentries ;
251
+
272
252
// stem the search terms and add them to the correct list
273
253
const stemmer = new Stemmer ( ) ;
274
254
const searchTerms = new Set ( ) ;
@@ -304,32 +284,16 @@ const Search = {
304
284
// console.info("required: ", [...searchTerms]);
305
285
// console.info("excluded: ", [...excludedTerms]);
306
286
307
- return [ query , searchTerms , excludedTerms , highlightTerms , objectTerms ] ;
308
- } ,
309
-
310
- /**
311
- * execute search (requires search index to be loaded)
312
- */
313
- _performSearch : ( query , searchTerms , excludedTerms , highlightTerms , objectTerms ) => {
314
- const filenames = Search . _index . filenames ;
315
- const docNames = Search . _index . docnames ;
316
- const titles = Search . _index . titles ;
317
- const allTitles = Search . _index . alltitles ;
318
- const indexEntries = Search . _index . indexentries ;
319
-
320
- // Collect multiple result groups to be sorted separately and then ordered.
321
- // Each is an array of [docname, title, anchor, descr, score, filename].
322
- const normalResults = [ ] ;
323
- const nonMainIndexResults = [ ] ;
324
-
287
+ // array of [docname, title, anchor, descr, score, filename]
288
+ let results = [ ] ;
325
289
_removeChildren ( document . getElementById ( "search-progress" ) ) ;
326
290
327
- const queryLower = query . toLowerCase ( ) . trim ( ) ;
291
+ const queryLower = query . toLowerCase ( ) ;
328
292
for ( const [ title , foundTitles ] of Object . entries ( allTitles ) ) {
329
- if ( title . toLowerCase ( ) . trim ( ) . includes ( queryLower ) && ( queryLower . length >= title . length / 2 ) ) {
293
+ if ( title . toLowerCase ( ) . includes ( queryLower ) && ( queryLower . length >= title . length / 2 ) ) {
330
294
for ( const [ file , id ] of foundTitles ) {
331
295
let score = Math . round ( 100 * queryLower . length / title . length )
332
- normalResults . push ( [
296
+ results . push ( [
333
297
docNames [ file ] ,
334
298
titles [ file ] !== title ? `${ titles [ file ] } > ${ title } ` : title ,
335
299
id !== null ? "#" + id : "" ,
@@ -344,47 +308,46 @@ const Search = {
344
308
// search for explicit entries in index directives
345
309
for ( const [ entry , foundEntries ] of Object . entries ( indexEntries ) ) {
346
310
if ( entry . includes ( queryLower ) && ( queryLower . length >= entry . length / 2 ) ) {
347
- for ( const [ file , id , isMain ] of foundEntries ) {
348
- const score = Math . round ( 100 * queryLower . length / entry . length ) ;
349
- const result = [
311
+ for ( const [ file , id ] of foundEntries ) {
312
+ let score = Math . round ( 100 * queryLower . length / entry . length )
313
+ results . push ( [
350
314
docNames [ file ] ,
351
315
titles [ file ] ,
352
316
id ? "#" + id : "" ,
353
317
null ,
354
318
score ,
355
319
filenames [ file ] ,
356
- ] ;
357
- if ( isMain ) {
358
- normalResults . push ( result ) ;
359
- } else {
360
- nonMainIndexResults . push ( result ) ;
361
- }
320
+ ] ) ;
362
321
}
363
322
}
364
323
}
365
324
366
325
// lookup as object
367
326
objectTerms . forEach ( ( term ) =>
368
- normalResults . push ( ...Search . performObjectSearch ( term , objectTerms ) )
327
+ results . push ( ...Search . performObjectSearch ( term , objectTerms ) )
369
328
) ;
370
329
371
330
// lookup as search terms in fulltext
372
- normalResults . push ( ...Search . performTermsSearch ( searchTerms , excludedTerms ) ) ;
331
+ results . push ( ...Search . performTermsSearch ( searchTerms , excludedTerms ) ) ;
373
332
374
333
// let the scorer override scores with a custom scoring function
375
- if ( Scorer . score ) {
376
- normalResults . forEach ( ( item ) => ( item [ 4 ] = Scorer . score ( item ) ) ) ;
377
- nonMainIndexResults . forEach ( ( item ) => ( item [ 4 ] = Scorer . score ( item ) ) ) ;
378
- }
379
-
380
- // Sort each group of results by score and then alphabetically by name.
381
- normalResults . sort ( _orderResultsByScoreThenName ) ;
382
- nonMainIndexResults . sort ( _orderResultsByScoreThenName ) ;
383
-
384
- // Combine the result groups in (reverse) order.
385
- // Non-main index entries are typically arbitrary cross-references,
386
- // so display them after other results.
387
- let results = [ ...nonMainIndexResults , ...normalResults ] ;
334
+ if ( Scorer . score ) results . forEach ( ( item ) => ( item [ 4 ] = Scorer . score ( item ) ) ) ;
335
+
336
+ // now sort the results by score (in opposite order of appearance, since the
337
+ // display function below uses pop() to retrieve items) and then
338
+ // alphabetically
339
+ results . sort ( ( a , b ) => {
340
+ const leftScore = a [ 4 ] ;
341
+ const rightScore = b [ 4 ] ;
342
+ if ( leftScore === rightScore ) {
343
+ // same score: sort alphabetically
344
+ const leftTitle = a [ 1 ] . toLowerCase ( ) ;
345
+ const rightTitle = b [ 1 ] . toLowerCase ( ) ;
346
+ if ( leftTitle === rightTitle ) return 0 ;
347
+ return leftTitle > rightTitle ? - 1 : 1 ; // inverted is intentional
348
+ }
349
+ return leftScore > rightScore ? 1 : - 1 ;
350
+ } ) ;
388
351
389
352
// remove duplicate search results
390
353
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
@@ -398,12 +361,7 @@ const Search = {
398
361
return acc ;
399
362
} , [ ] ) ;
400
363
401
- return results . reverse ( ) ;
402
- } ,
403
-
404
- query : ( query ) => {
405
- const [ searchQuery , searchTerms , excludedTerms , highlightTerms , objectTerms ] = Search . _parseQuery ( query ) ;
406
- const results = Search . _performSearch ( searchQuery , searchTerms , excludedTerms , highlightTerms , objectTerms ) ;
364
+ results = results . reverse ( ) ;
407
365
408
366
// for debugging
409
367
//Search.lastresults = results.slice(); // a copy
@@ -508,18 +466,14 @@ const Search = {
508
466
// add support for partial matches
509
467
if ( word . length > 2 ) {
510
468
const escapedWord = _escapeRegExp ( word ) ;
511
- if ( ! terms . hasOwnProperty ( word ) ) {
512
- Object . keys ( terms ) . forEach ( ( term ) => {
513
- if ( term . match ( escapedWord ) )
514
- arr . push ( { files : terms [ term ] , score : Scorer . partialTerm } ) ;
515
- } ) ;
516
- }
517
- if ( ! titleTerms . hasOwnProperty ( word ) ) {
518
- Object . keys ( titleTerms ) . forEach ( ( term ) => {
519
- if ( term . match ( escapedWord ) )
520
- arr . push ( { files : titleTerms [ term ] , score : Scorer . partialTitle } ) ;
521
- } ) ;
522
- }
469
+ Object . keys ( terms ) . forEach ( ( term ) => {
470
+ if ( term . match ( escapedWord ) && ! terms [ word ] )
471
+ arr . push ( { files : terms [ term ] , score : Scorer . partialTerm } ) ;
472
+ } ) ;
473
+ Object . keys ( titleTerms ) . forEach ( ( term ) => {
474
+ if ( term . match ( escapedWord ) && ! titleTerms [ word ] )
475
+ arr . push ( { files : titleTerms [ word ] , score : Scorer . partialTitle } ) ;
476
+ } ) ;
523
477
}
524
478
525
479
// no match but word was a required one
@@ -542,8 +496,9 @@ const Search = {
542
496
543
497
// create the mapping
544
498
files . forEach ( ( file ) => {
545
- if ( ! fileMap . has ( file ) ) fileMap . set ( file , [ word ] ) ;
546
- else if ( fileMap . get ( file ) . indexOf ( word ) === - 1 ) fileMap . get ( file ) . push ( word ) ;
499
+ if ( fileMap . has ( file ) && fileMap . get ( file ) . indexOf ( word ) === - 1 )
500
+ fileMap . get ( file ) . push ( word ) ;
501
+ else fileMap . set ( file , [ word ] ) ;
547
502
} ) ;
548
503
} ) ;
549
504
@@ -594,8 +549,8 @@ const Search = {
594
549
* search summary for a given text. keywords is a list
595
550
* of stemmed words.
596
551
*/
597
- makeSearchSummary : ( htmlText , keywords , anchor ) => {
598
- const text = Search . htmlToText ( htmlText , anchor ) ;
552
+ makeSearchSummary : ( htmlText , keywords ) => {
553
+ const text = Search . htmlToText ( htmlText ) ;
599
554
if ( text === "" ) return null ;
600
555
601
556
const textLower = text . toLowerCase ( ) ;
0 commit comments