feat: full-text search across all doc modules
This commit is contained in:
@@ -142,6 +142,42 @@ async function loadDoc(name) {
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(s) {
|
||||
return s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user