"""PDF generation from Markdown using markdown-pdf.""" from io import BytesIO from pathlib import Path from typing import Optional from markdown_pdf import MarkdownPdf, Section _PROJECT_ROOT = Path(__file__).resolve().parent.parent def markdown_to_pdf( md_text: str, toc_level: int = 2, logo_path: Optional[str] = None, ) -> BytesIO: """Convert Markdown to PDF using markdown-pdf (PyMuPDF + markdown-it-py). Supports UTF-8, tables, links, images, and TOC from headings. Optionally adds a dedicated logo section at the top (centered) if logo_path is set. """ if logo_path is None: try: from config.settings import settings logo_path = getattr(settings, "pdf_logo_path", None) except Exception: logo_path = None pdf = MarkdownPdf(toc_level=toc_level, optimize=True) # Section 1: logo centered at top (if file exists) logo_file = _PROJECT_ROOT / logo_path if logo_path else None if logo_file and logo_file.is_file(): logo_md = f"![Logo]({logo_path})" logo_css = "img { display: block; margin-left: auto; margin-right: auto; }" logo_section = Section(logo_md, toc=False) logo_section.root = str(_PROJECT_ROOT) pdf.add_section(logo_section, user_css=logo_css) # Section 2: main content (réduit la police) content_css = ( "body, p, li, ul, ol, td, th { font-size: 9pt; } " "h1 { font-size: 14pt; } h2 { font-size: 12pt; } h3 { font-size: 10pt; }" ) content_section = Section(md_text) content_section.root = str(_PROJECT_ROOT) pdf.add_section(content_section, user_css=content_css) buffer = BytesIO() pdf.save_bytes(buffer) buffer.seek(0) return buffer