left4me/l4d2web/scripts/editor-src/vocab-rank.js
mwiegand 9ff93164d7
feat(editor): extract pure rankVocab module + tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 17:33:26 +02:00

37 lines
1.2 KiB
JavaScript

// Pure, dependency-free ranking of a vocabulary against a query string.
// Used by both the CodeMirror editor (via autocomplete.js) and the
// runtime console (via the vocab-rank bundle exposed on window).
//
// Score (lower = better):
// exact match → 0
// prefix match → 1 + label.length (shorter prefix matches win)
// substring match → 10000 + indexOf (earlier substring beats later)
// no match → -1 (excluded)
function score(query, label) {
if (label === query) return 0;
if (label.startsWith(query)) return 1 + label.length;
const i = label.indexOf(query);
if (i !== -1) return 10000 + i;
return -1;
}
export function rankVocab(query, vocab, { limit = 50 } = {}) {
if (!query) return [];
const q = query.toLowerCase();
const entries = [
...vocab.cvars.map(e => ({ ...e, kind: "cvar" })),
...vocab.commands.map(e => ({ ...e, kind: "command" })),
];
const scored = [];
for (const e of entries) {
const s = score(q, e.name.toLowerCase());
if (s === -1) continue;
scored.push([s, e]);
if (scored.length > limit * 4) break;
}
scored.sort((a, b) => a[0] - b[0]);
return scored.slice(0, limit).map(([, e]) => e);
}