feat: full-text search across all doc modules

This commit is contained in:
Accusys
2026-05-19 03:18:36 +08:00
parent b046a3b91c
commit 7bc069b806

View File

@@ -142,6 +142,42 @@ async function loadDoc(name) {
}
}
function escapeHtml(s) {
return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
async function fulltextSearch(q) {
el.innerHTML = '<p>Searching...</p>';
var results = [];
for (var i = 0; i < MODULES.length; i++) {
var m = MODULES[i];
try {
var resp = await fetch('/doc-wasm/modules/' + m[0] + '.md');
if (!resp.ok) continue;
var md = await resp.text();
var lines = md.split('\n');
for (var li = 0; li < lines.length; li++) {
if (lines[li].toLowerCase().indexOf(q) >= 0) {
results.push({ module: m[0], title: m[1] + ' / ' + m[2], line: li + 1, text: lines[li].trim() });
if (results.length > 50) break;
}
}
} catch(e) {}
}
if (results.length === 0) {
el.innerHTML = '<p>No results for <strong>' + escapeHtml(q) + '</strong></p>';
return;
}
var html = '<h2>Search: ' + escapeHtml(q) + '</h2><p>' + results.length + ' result(s)</p>';
for (var r of results) {
html += '<p style="margin:4px 0"><a href="#" onclick="loadDoc(\'' + r.module + '\');return false" style="font-weight:600">'
+ r.module + ' ' + escapeHtml(r.title) + '</a> <span style="color:#888;font-size:12px">line ' + r.line + '</span><br>'
+ '<code style="background:#f5f5f5;padding:2px 6px;border-radius:3px;font-size:12px;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'
+ escapeHtml(r.text) + '</code></p>';
}
el.innerHTML = html;
}
async function loginUser(user, pass) {
var resp = await fetch('/api/v1/auth/login', {
method:'POST', headers:{'Content-Type':'application/json'},
@@ -187,14 +223,18 @@ async function initApp() {
a.onclick = function(e) { e.preventDefault(); loadDoc(m[0]); };
listEl.appendChild(a);
});
// Search filter
// Search — full text across all modules
var searchTimer = null;
var searchEl = document.getElementById('search');
if (searchEl) {
searchEl.oninput = function() {
var q = this.value.toLowerCase();
var q = this.value.toLowerCase().trim();
document.querySelectorAll('#module-list a').forEach(function(a) {
a.style.display = a.textContent.toLowerCase().indexOf(q) >= 0 ? '' : 'none';
});
if (searchTimer) clearTimeout(searchTimer);
if (q.length < 2) { loadDoc(location.hash.slice(1) || '01_auth'); return; }
searchTimer = setTimeout(function() { fulltextSearch(q); }, 300);
};
}
// Watch for logout disappearing