// Turn glossary entries into flashcard seeds. Deterministic, no model. // A seed is a UI-friendly front/back pair carrying its source provenance; the // repo later wraps it into a FlashcardDraft + SRS state. // // IMPORTANT: relative imports only inside src/lib (vitest has no '@/*' alias). import type { GlossaryEntry } from './glossary'; /** A front/back pair for a flashcard, with optional source anchor. */ export interface CardSeed { front: string; back: string; /** Source segment id, for click-to-seek. */ segmentId?: string; /** Source start time (seconds). */ start?: number; } /** * Build one {@link CardSeed} per glossary entry. * * Front: if the term appears verbatim (case-insensitively) inside the * definition, we make a cloze deletion — blanking the term in the definition so * the learner recalls it in context. Otherwise we fall back to the plain * "What is {term}?" prompt. Back is always the full definition. */ export function cardsFromGlossary(entries: GlossaryEntry[]): CardSeed[] { return entries.map((entry) => { const front = makeFront(entry.term, entry.definition); return { front, back: entry.definition, segmentId: entry.segmentId, start: entry.start, }; }); } /** "_____" cloze if the term occurs in the definition, else a Q prompt. */ function makeFront(term: string, definition: string): string { const re = new RegExp(escapeRegExp(term), 'i'); if (re.test(definition)) { return definition.replace(re, '_____'); } return `What is ${term}?`; } /** Escape a string for safe use inside a RegExp. */ function escapeRegExp(s: string): string { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }