@@ -471,16 +471,66 @@ window.search = window.search || {};
471471 showResults ( true ) ;
472472 }
473473
474- var branch = lang === "en" ? "master" : lang
475- fetch ( `https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/refs/heads/${ branch } /searchindex.json` )
476- . then ( response => response . json ( ) )
477- . then ( json => init ( json ) )
478- . catch ( error => { // Try to load searchindex.js if fetch failed
479- var script = document . createElement ( 'script' ) ;
480- script . src = `https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/refs/heads/${ branch } /searchindex.js` ;
481- script . onload = ( ) => init ( window . search ) ;
482- document . head . appendChild ( script ) ;
483- } ) ;
474+ ( async function loadSearchIndex ( lang = window . lang || 'en' ) {
475+ /* ───────── paths ───────── */
476+ const branch = lang === 'en' ? 'master' : lang ;
477+ const baseRemote = `https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/${ branch } ` ;
478+ const remoteJson = `${ baseRemote } /searchindex.json` ;
479+ const remoteJs = `${ baseRemote } /searchindex.js` ;
480+ const localJson = './searchindex.json' ;
481+ const localJs = './searchindex.js' ;
482+ const TIMEOUT_MS = 5_000 ;
483+
484+ /* ───────── helpers ───────── */
485+ const fetchWithTimeout = ( url , opt = { } ) =>
486+ Promise . race ( [
487+ fetch ( url , opt ) ,
488+ new Promise ( ( _ , r ) => setTimeout ( ( ) => r ( new Error ( 'timeout' ) ) , TIMEOUT_MS ) )
489+ ] ) ;
490+
491+ const loadScript = src =>
492+ new Promise ( ( resolve , reject ) => {
493+ const s = document . createElement ( 'script' ) ;
494+ s . src = src ;
495+ s . onload = resolve ;
496+ s . onerror = reject ;
497+ document . head . appendChild ( s ) ;
498+ } ) ;
499+
500+ /* ───────── 1. remote JSON ───────── */
501+ try {
502+ const r = await fetchWithTimeout ( remoteJson ) ;
503+ if ( ! r . ok ) throw new Error ( r . status ) ;
504+ return init ( await r . json ( ) ) ;
505+ } catch ( e ) {
506+ console . warn ( 'Remote JSON failed →' , e ) ;
507+ }
508+
509+ /* ───────── 2. remote JS ───────── */
510+ try {
511+ await loadScript ( remoteJs ) ;
512+ return init ( window . search ) ;
513+ } catch ( e ) {
514+ console . warn ( 'Remote JS failed →' , e ) ;
515+ }
516+
517+ /* ───────── 3. local JSON ───────── */
518+ try {
519+ const r = await fetch ( localJson ) ;
520+ if ( ! r . ok ) throw new Error ( r . status ) ;
521+ return init ( await r . json ( ) ) ;
522+ } catch ( e ) {
523+ console . warn ( 'Local JSON failed →' , e ) ;
524+ }
525+
526+ /* ───────── 4. local JS ───────── */
527+ try {
528+ await loadScript ( localJs ) ;
529+ return init ( window . search ) ;
530+ } catch ( e ) {
531+ console . error ( 'Local JS failed →' , e ) ;
532+ }
533+ } ) ( ) ;
484534
485535 // Exported functions
486536 search . hasFocus = hasFocus ;
0 commit comments