1
1
/*
2
- * Sphinx search overrides
2
+ * Sphinx and Mkdocs search overrides
3
3
*/
4
4
5
5
var rtddata = require ( './rtd-data' ) ;
@@ -40,7 +40,7 @@ function append_html_to_contents(contents, template, data) {
40
40
* Sphinx indexer. This will fall back to the standard indexer on an API
41
41
* failure,
42
42
*/
43
- function attach_elastic_search_query ( data ) {
43
+ function attach_elastic_search_query_sphinx ( data ) {
44
44
var project = data . project ;
45
45
var version = data . version ;
46
46
var language = data . language || 'en' ;
@@ -56,7 +56,6 @@ function attach_elastic_search_query(data) {
56
56
search_def
57
57
. then ( function ( data ) {
58
58
var hit_list = data . results || [ ] ;
59
- var total_count = data . count || 0 ;
60
59
61
60
if ( hit_list . length ) {
62
61
for ( var i = 0 ; i < hit_list . length ; i += 1 ) {
@@ -265,12 +264,13 @@ function attach_elastic_search_query(data) {
265
264
} ;
266
265
267
266
if ( typeof Search !== 'undefined' && project && version ) {
268
-
269
267
// Do not replace the built-in search if RTD's docsearch is disabled
270
268
if ( ! data . features || ! data . features . docsearch_disabled ) {
271
269
var query_fallback = Search . query ;
272
270
Search . query_fallback = query_fallback ;
273
271
Search . query = query_override ;
272
+ } else {
273
+ console . log ( 'Server side search is disabled.' ) ;
274
274
}
275
275
}
276
276
$ ( document ) . ready ( function ( ) {
@@ -281,9 +281,179 @@ function attach_elastic_search_query(data) {
281
281
}
282
282
283
283
284
+ /*
285
+ * Mkdocs search override for hitting our API instead of the standard Mkdocs search index.
286
+ * This will fall back to the original search on an API failure.
287
+ */
288
+ function attach_elastic_search_query_mkdocs ( data ) {
289
+ var project = data . project ;
290
+ var version = data . version ;
291
+ var language = data . language || 'en' ;
292
+
293
+ var fallbackSearch = function ( ) {
294
+ if ( typeof window . doSearchFallback !== 'undefined' ) {
295
+ window . doSearchFallback ( ) ;
296
+ } else {
297
+ console . log ( 'Unable to fallback to original MkDocs search.' ) ;
298
+ }
299
+ } ;
300
+
301
+ var doSearch = function ( ) {
302
+ var query = document . getElementById ( 'mkdocs-search-query' ) . value ;
303
+
304
+ var search_def = $ . Deferred ( ) ;
305
+
306
+ var search_url = document . createElement ( 'a' ) ;
307
+ search_url . href = data . proxied_api_host + '/api/v2/docsearch/' ;
308
+ search_url . search = '?q=' + encodeURIComponent ( query ) + '&project=' + project +
309
+ '&version=' + version + '&language=' + language ;
310
+
311
+ search_def
312
+ . then ( function ( data ) {
313
+ var hit_list = data . results || [ ] ;
314
+
315
+ if ( hit_list . length ) {
316
+ var searchResults = $ ( '#mkdocs-search-results' ) ;
317
+ searchResults . empty ( ) ;
318
+
319
+ for ( var i = 0 ; i < hit_list . length ; i += 1 ) {
320
+ var doc = hit_list [ i ] ;
321
+ var inner_hits = doc . inner_hits || [ ] ;
322
+
323
+ var result = $ ( '<article>' ) ;
324
+ result . append (
325
+ $ ( '<h3>' ) . append ( $ ( '<a>' , { 'href' : doc . link , 'text' : doc . title } ) )
326
+ ) ;
327
+
328
+ if ( doc . project !== project ) {
329
+ var text = '(from project ' + doc . project + ')' ;
330
+ result . append ( $ ( '<span>' , { 'text' : text } ) ) ;
331
+ }
332
+
333
+ for ( var j = 0 ; j < inner_hits . length ; j += 1 ) {
334
+ var section = inner_hits [ j ] ;
335
+
336
+ if ( section . type === 'sections' ) {
337
+ var section_link = doc . link + '#' + section . _source . id ;
338
+ var section_title = section . _source . title ;
339
+ var section_content = section . _source . content ;
340
+ if ( section_content . length > MAX_SUBSTRING_LIMIT ) {
341
+ section_content = section_content . substr ( 0 , MAX_SUBSTRING_LIMIT ) + " ..." ;
342
+ }
343
+ var section_contents = [ section_content ] ;
344
+
345
+ if ( section . highlight ) {
346
+ if ( section . highlight [ "sections.title" ] ) {
347
+ section_title = section . highlight [ "sections.title" ] [ 0 ] ;
348
+ }
349
+ if ( section . highlight [ "sections.content" ] ) {
350
+ var contents = section . highlight [ "sections.content" ] ;
351
+ section_contents = [ ] ;
352
+ for (
353
+ var k = 0 ;
354
+ k < contents . length && k < MAX_RESULT_PER_SECTION ;
355
+ k += 1
356
+ ) {
357
+ section_contents . push ( "... " + contents [ k ] + " ..." ) ;
358
+ }
359
+ }
360
+ }
361
+
362
+ section_title = xss ( section_title )
363
+ . replace ( / < s p a n > / g, '<mark>' )
364
+ . replace ( / < \/ s p a n > / g, '</mark>' ) ;
365
+ result . append (
366
+ $ ( '<h4>' )
367
+ . append ( $ ( '<a>' , { 'href' : section_link } ) . html ( section_title ) )
368
+ ) ;
369
+ for ( var m = 0 ; m < section_contents . length ; m += 1 ) {
370
+ var content = xss ( section_contents [ m ] ) ;
371
+ content = content
372
+ . replace ( / < s p a n > / g, '<mark>' )
373
+ . replace ( / < \/ s p a n > / g, '</mark>' ) ;
374
+ result . append (
375
+ $ ( '<p>' ) . html ( content )
376
+ ) ;
377
+ }
378
+ searchResults . append ( result ) ;
379
+ }
380
+ }
381
+ }
382
+ } else {
383
+ console . log ( 'Read the Docs search returned 0 result. Falling back to MkDocs search.' ) ;
384
+ fallbackSearch ( ) ;
385
+ }
386
+ } )
387
+ . fail ( function ( error ) {
388
+ console . log ( 'Read the Docs search failed. Falling back to MkDocs search.' ) ;
389
+ fallbackSearch ( ) ;
390
+ } ) ;
391
+
392
+ $ . ajax ( {
393
+ url : search_url . href ,
394
+ crossDomain : true ,
395
+ xhrFields : {
396
+ withCredentials : true ,
397
+ } ,
398
+ complete : function ( resp , status_code ) {
399
+ if (
400
+ status_code !== 'success' ||
401
+ typeof ( resp . responseJSON ) === 'undefined' ||
402
+ resp . responseJSON . count === 0
403
+ ) {
404
+ return search_def . reject ( ) ;
405
+ }
406
+ return search_def . resolve ( resp . responseJSON ) ;
407
+ }
408
+ } )
409
+ . fail ( function ( resp , status_code , error ) {
410
+ return search_def . reject ( ) ;
411
+ } ) ;
412
+ } ;
413
+
414
+ var initSearch = function ( ) {
415
+ var search_input = document . getElementById ( 'mkdocs-search-query' ) ;
416
+ if ( search_input ) {
417
+ search_input . addEventListener ( 'keyup' , doSearch ) ;
418
+ }
419
+
420
+ var term = window . getSearchTermFromLocation ( ) ;
421
+ if ( term ) {
422
+ search_input . value = term ;
423
+ doSearch ( ) ;
424
+ }
425
+ } ;
426
+
427
+ $ ( document ) . ready ( function ( ) {
428
+ // We can't override the search completely,
429
+ // because we can't delete the original event listener,
430
+ // and MkDocs includes its search functions after ours.
431
+ // If MkDocs is loaded before, this will trigger a double search
432
+ // (but ours will have precendece).
433
+
434
+ // Note: this function is only available on Mkdocs >=1.x
435
+ window . doSearchFallback = window . doSearch ;
436
+
437
+ window . doSearch = doSearch ;
438
+ window . initSearch = initSearch ;
439
+ initSearch ( ) ;
440
+ } ) ;
441
+ }
442
+
443
+
284
444
function init ( ) {
285
445
var data = rtddata . get ( ) ;
286
- attach_elastic_search_query ( data ) ;
446
+ if ( data . is_sphinx_builder ( ) ) {
447
+ // Check to disabled server side search for Sphinx
448
+ // happens inside the function, because we still need to call Search.init().
449
+ attach_elastic_search_query_sphinx ( data ) ;
450
+ }
451
+ // MkDocs projects should have this flag explicitly for now.
452
+ else if ( data . features && ! data . features . docsearch_disabled ) {
453
+ attach_elastic_search_query_mkdocs ( data ) ;
454
+ } else {
455
+ console . log ( 'Server side search is disabled.' ) ;
456
+ }
287
457
}
288
458
289
459
module . exports = {
0 commit comments