"""Render QuizSet/FlashcardSet as self-contained interactive HTML. All interactivity runs in the browser. ``""" # --------------------------------------------------------------------------- # Quiz (click-to-answer with instant feedback) # --------------------------------------------------------------------------- def render_quiz_html(quiz_set: QuizSet) -> str: """Return HTML with quiz data in ``data-quiz`` attribute for the MutationObserver.""" if not quiz_set.items: return '
No questions available.
' citation_map = { citation.source_marker: { "marker": citation.source_marker, "filename": citation.filename, "page": citation.page, "text": citation.source_text or "", } for citation in quiz_set.citations } data = [ { "q": item.question, "opts": item.options, "correct": item.correct_index, "explanation": item.explanation or "No explanation provided.", "difficulty": item.difficulty or "", "sources": [ citation_map[marker] for marker in item.source_markers if marker in citation_map ], } for item in quiz_set.items ] data_json = json.dumps(data, ensure_ascii=False) scope_escaped = html_mod.escape( f"{quiz_set.scope}: {quiz_set.target}" if quiz_set.target else quiz_set.scope ) SVG_OK = ( '' '' ) SVG_BAD = ( '' '' '' ) return f"""
{scope_escaped} 0 / {len(data)} answered
Mode 1–4 answer · Enter next
""" # --------------------------------------------------------------------------- # Flashcards (3D card flip with prev / next / shuffle) # --------------------------------------------------------------------------- def render_flashcard_html(flashcard_set: FlashcardSet) -> str: """Return HTML with flashcard data in ``data-cards`` attribute for the MutationObserver.""" if not flashcard_set.cards: return '
No cards available.
' citation_map = { citation.source_marker: { "marker": citation.source_marker, "filename": citation.filename, "page": citation.page, "text": citation.source_text or "", } for citation in flashcard_set.citations } data = [ { "front": card.front, "back": card.back, "hint": card.hint or "", "sources": [ citation_map[marker] for marker in card.source_markers if marker in citation_map ], } for card in flashcard_set.cards ] data_json = json.dumps(data, ensure_ascii=False) scope_escaped = html_mod.escape( f"{flashcard_set.scope}: {flashcard_set.target}" if flashcard_set.target else flashcard_set.scope ) SVG_PREV = ( '' ) SVG_NEXT = ( '' ) SVG_SHUFFLE = ( '' '' '' '' '' '' ) return f"""
{scope_escaped} 1 / {len(data)}

Question

Tap to reveal

Answer

"""