let lunrIndex; let documents = []; /* ------------------------------ JSON → documents -------------------------------- */ function extractDocuments(node, currentPath = "") { if (node.type === "folder" && node.children) { const nextPath = currentPath ? `${currentPath}/${node.name}` : node.name; node.children.forEach(child => { extractDocuments(child, nextPath); }); } if (node.type === "file") { const filePath = currentPath ? `${currentPath}/${node.name}` : node.name; documents.push({ id: documents.length.toString(), title: node.name, content: node.content || "", path: "/" + filePath.replace(/^output\//, "") }); } } /* ------------------------------ Lunr index -------------------------------- */ function buildIndex() { lunrIndex = lunr(function () { this.ref("id"); this.field("title", { boost: 10 }); this.field("content"); documents.forEach(doc => this.add(doc)); }); console.log("Lunr index built with", documents.length, "documents"); } async function initSearch() { const response = await fetch("test.json"); const json = await response.json(); extractDocuments(json); buildIndex(); } initSearch(); /* ------------------------------ Fuzzy search -------------------------------- */ function buildFuzzyQuery(query) { return query .split(/\s+/) .map(term => `${term}~1`) .join(" "); } function search(query) { if (!lunrIndex) return []; const results = lunrIndex.search(buildFuzzyQuery(query)); return results.map(r => { const doc = documents.find(d => d.id === r.ref); return { title: doc.title, path: doc.path, score: r.score, preview: doc.content.slice(0, 200) + "…" }; }); } /* ------------------------------ DOM elements -------------------------------- */ const searchInput = document.getElementById("search-input"); const searchBtn = document.getElementById("search-btn"); /* ------------------------------ Live dropdown results -------------------------------- */ const resultsBox = document.createElement("div"); resultsBox.id = "search-results"; document.body.appendChild(resultsBox); function showResults(results) { resultsBox.innerHTML = ""; if (results.length === 0) { resultsBox.style.display = "none"; return; } const rect = searchInput.getBoundingClientRect(); resultsBox.style.top = `${rect.bottom + window.scrollY}px`; resultsBox.style.left = `${rect.left + window.scrollX}px`; resultsBox.style.width = `${rect.width}px`; results.slice(0, 5).forEach(result => { const item = document.createElement("div"); item.className = "search-result"; item.innerHTML = `
No results found.
"; } results.forEach(result => { const item = document.createElement("div"); item.className = "search-modal-result"; item.innerHTML = `