"""Export a forged case+note to downloadable files. Per the MVP cut-lines, PDF is optional and Markdown is the floor. We ship two zero-dependency formats: a clean **Markdown** file (the canonical artifact) and a self-contained **printable HTML** the instructor can open and Print-to-PDF — covering the PDF use case without a PDF toolchain in the Space. """ from __future__ import annotations import re import tempfile from pathlib import Path def _slug(title: str) -> str: s = re.sub(r"[^\w\s-]", "", (title or "case").lower()).strip() s = re.sub(r"[\s_-]+", "-", s) return (s or "case")[:60] def _combined_markdown(case_md: str, note_md: str) -> str: return f"{(case_md or '').strip()}\n\n---\n\n{(note_md or '').strip()}\n" def _md_inline(text: str) -> str: """Minimal inline Markdown → HTML: **bold** and escaping.""" import html text = html.escape(text) return re.sub(r"\*\*(.+?)\*\*", r"\1", text) def _md_to_html_body(md: str) -> str: """Tiny Markdown→HTML for our own controlled output (headings, lists, quotes).""" lines = md.splitlines() html_lines: list[str] = [] list_type: str | None = None # 'ul' | 'ol' def close_list(): nonlocal list_type if list_type: html_lines.append(f"{list_type}>") list_type = None for raw in lines: line = raw.rstrip() if not line.strip(): close_list() continue if line.startswith("# "): close_list(); html_lines.append(f"
{_md_inline(line[2:])}") elif line.strip() == "---": close_list(); html_lines.append("
{_md_inline(line)}
") close_list() return "\n".join(html_lines) _HTML_SHELL = """