diff --git a/theme/ht_searcher.js b/theme/ht_searcher.js index dfed69d36..db9b55b76 100644 --- a/theme/ht_searcher.js +++ b/theme/ht_searcher.js @@ -1,96 +1,92 @@ -/* ht_searcher.js ───────────────────────────────────────────────── */ -/* Everything – UI + worker – lives in this one file. */ - +/* ht_searcher.js ─────────────────────────────────────────────── */ (() => { - /* ────────────────────────────── - 0. Build an inline Web Worker - ────────────────────────────── */ + /* ───────────── 0. Inline Web-Worker code ────────────────────── */ const workerCode = ` - /* inside the worker thread ################################## */ - self.window = self; /* let searchindex.js use window */ - - /* 1. elasticlunr.min.js (CDN → local) */ + /* Make scripts written for browsers happy inside the worker */ + self.window = self; + self.search = self.search || {}; /* ensure object */ + + const abs = p => location.origin + p; /* helper */ + + /* 1 ─ elasticlunr.min.js (CDN → local) */ try { importScripts('https://cdn.jsdelivr.net/npm/elasticlunr@0.9.5/elasticlunr.min.js'); - } catch (_) { - importScripts('/elasticlunr.min.js'); + } catch (e) { + console.error('elasticlunr CDN failed →', e); + importScripts(abs('/elasticlunr.min.js')); } - - /* 2. searchindex.js (GitHub Raw → local) */ + + /* 2 ─ searchindex.js (GitHub Raw → local) */ (async () => { try { const r = await fetch( 'https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/refs/heads/master/searchindex.js', - { mode: 'cors' } + { mode:'cors' } ); - if (!r.ok) throw new Error(r.status); + if (!r.ok) throw new Error('HTTP ' + r.status); const blobURL = URL.createObjectURL( - new Blob([await r.text()], { type: 'application/javascript' }) - ); /* force correct MIME */ - importScripts(blobURL); - } catch (_) { - importScripts('/searchindex.js'); + new Blob([await r.text()], { type:'application/javascript' }) + ); + importScripts(blobURL); /* MIME coercion */ + } catch (e) { + console.error('GitHub index fetch failed →', e); + try { + importScripts(abs('/searchindex.js')); + } catch (e2) { + console.error('Local index load failed →', e2); + throw e2; /* abort loudly */ + } } - - /* 3. Build index & reply to queries */ + + /* 3 ─ build index & answer queries */ const idx = elasticlunr.Index.load(self.search.index); - - self.onmessage = ({ data: q }) => { - const hits = idx.search(q, { bool: 'AND', expand: true }); - postMessage(hits); + + self.onmessage = ({ data:q }) => { + if (!q) { postMessage([]); return; } /* empty search */ + const raw = idx.search(q, { bool:'AND', expand:true }); + const docs = raw.map(r => idx.documentStore.getDoc(r.ref)); + postMessage(docs); /* only docs cross thread */ }; })(); `; - - /* Turn the string into a real worker file */ + const workerURL = URL.createObjectURL( - new Blob([workerCode], { type: 'application/javascript' }) + new Blob([workerCode], { type:'application/javascript' }) ); - const worker = new Worker(workerURL); /* classic worker, supports importScripts */ - URL.revokeObjectURL(workerURL); /* clean up */ - - /* ────────────────────────────── - 1. Minimal search-UI glue - ────────────────────────────── */ - const WRAP = document.getElementById('search-wrapper'); - const TOG = document.getElementById('search-toggle'); - const INP = document.getElementById('searchbar'); - const LIST = document.getElementById('searchresults'); + const worker = new Worker(workerURL); + URL.revokeObjectURL(workerURL); /* tidy blob */ + + /* ───────────── 1. Tiny UI glue ─────────────────────────────── */ + const WRAP = document.getElementById('search-wrapper'); + const TOG = document.getElementById('search-toggle'); + const INP = document.getElementById('searchbar'); + const LIST = document.getElementById('searchresults'); const HOTKEY = 83; /* “s” */ let debounce; - - /* Paint results that come back from the worker */ - const paint = hits => { - LIST.innerHTML = hits.slice(0, 30).map(h => - '