/* Declarations for lib/lexicon.js — the module itself ships unchanged. One resolver shared by word lookup and the gate, so the two cannot drift. heads() returns EVERY route from a surface form to a dictionary word; a single "best" answer was the bug. */ export const PARTICLES: string[]; export interface LexEntry { ko: string; gloss: string; note: string; /** roadmap | deck | form | gloss | sentence | sfx */ src: string; /** The dictionary word this entry is a form of, or "". */ base: string; } export class Lexicon { map: Map; verbs: Set; /** First writer wins: an existing entry is never replaced. */ add(ko: string, gloss: string, note?: string, src?: string, base?: string): void; addVerb(dictionaryForm: string): void; get(ko: string): LexEntry | null; isVerb(ko: string): boolean; /** Every dictionary word this surface form could be, best first. */ heads(token: string): string[]; /** What to show when the student taps a word. */ lookup(token: string): LexEntry | null; } /** A deck row: [한글, romanization, English, POS], or the same as an object. */ export type DeckWord = | { ko: string; en: string; pos: string } | readonly [string, string, string, string]; export interface LexiconSources { /** Entered FIRST, with no base — see the ordering warning in lexicon.js. */ roadmapWords?: string[]; deck?: DeckWord[]; /** [한글, English, note?] */ glossExtra?: (readonly [string, string, string?])[]; sentences?: { parts?: (readonly [string, string, ...unknown[]])[] }[]; /** [한글, English] */ sfx?: (readonly [string, string])[]; } export function buildLexicon( sources: LexiconSources, conjugation: { haeche: (dict: string) => string | null; past: (present: string | null) => string | null; }, ): Lexicon;