',
f'
{number}'
f'{path}
',
f'
{text_html(question.get("question", ""))}
',
]
q_image = media.image_html(question.get("picture_question"))
if q_image:
front_parts.append(
f'
{q_image}
'
)
front_parts.append('
')
for choice in choices:
choice_image = media.image_html(choice.get("picture"))
image_html_part = (
f'{choice_image}
' if choice_image else ""
)
front_parts.append(
"- "
f'
{text_html(choice["text"])}
'
f"{image_html_part}"
" "
)
front_parts.append("
")
correct_image = media.image_html(correct.get("picture"))
back_parts = [
'',
f'
Richtige Antwort: {correct_label}
',
f'
{text_html(correct["text"])}
',
]
if correct_image:
back_parts.append(
f'
{correct_image}
'
)
back_parts.append("
")
return "".join(front_parts), "".join(back_parts), correct_label
def display_path(path):
"""Return the user-facing section path with the top prefix stripped.
Used for both the visible card breadcrumb and the stored `Path`
note field so the two never drift.
"""
if not path:
return ""
return " / ".join([_short_category_title(path[0]), *path[1:]])
# ============================================================================
# LaTeX and HTML escaping
# ============================================================================
def text_html(value):
"""Escape text for HTML, preserve line breaks, and enable MathJax.
The catalog uses bare `$...$` for inline LaTeX (DESIGN.md §3
quotes the upstream README on this). Anki 2.1+ ships built-in
MathJax that recognizes `\\(...\\)` but not `$...$`, so we
tokenize the input into alternating math / non-math runs, escape
each run for HTML, and wrap math runs in `\\(...\\)` afterwards.
Non-math newlines become `