(() => { const input = document.getElementById("homeToolSearch"); const results = document.getElementById("homeSearchResults"); const dataEl = document.getElementById("searchable-tools-data"); if (!input || !results || !dataEl) return; let tools = []; try { tools = JSON.parse(dataEl.textContent || "[]"); } catch { tools = []; } const MAX_RESULTS = 8; function scoreTool(tool, term) { const name = (tool.name || "").toLowerCase(); const slug = (tool.slug || "").toLowerCase(); const description = (tool.description || "").toLowerCase(); if (name === term) return 100; if (slug === term) return 95; if (name.startsWith(term)) return 80; if (slug.startsWith(term)) return 70; if (name.includes(term)) return 55; if (description.includes(term)) return 35; return 0; } function render(items, term) { if (!term) { results.innerHTML = ""; results.classList.remove("is-visible"); return; } if (!items.length) { results.innerHTML = '
No tools found.
'; results.classList.add("is-visible"); return; } const escapeHtml = (value) => String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/\"/g, """) .replace(/'/g, "'"); const rows = items.map((tool) => { const safeName = escapeHtml(tool.name || ""); const safeSlug = escapeHtml(tool.slug || ""); return ( `` + `${safeName}` + `` ); }); results.innerHTML = rows.join(""); results.classList.add("is-visible"); } function runSearch() { const term = input.value.trim().toLowerCase(); if (!term) { render([], ""); return []; } const filtered = tools .map((tool) => ({ tool, score: scoreTool(tool, term) })) .filter((entry) => entry.score > 0) .sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name)) .slice(0, MAX_RESULTS) .map((entry) => entry.tool); render(filtered, term); return filtered; } input.addEventListener("input", runSearch); input.addEventListener("keydown", (event) => { if (event.key !== "Enter") return; event.preventDefault(); const items = runSearch(); if (items.length) { window.location.href = `/${items[0].slug}.html`; } }); document.addEventListener("click", (event) => { if (event.target === input || results.contains(event.target)) return; results.classList.remove("is-visible"); }); })();