any-file to PDF (Phase 1): converters/ dispatcher, images/text/md/csv/json/xml/svg/pdf-passthrough, 112 tests green

This commit is contained in:
sirdave73
2026-09-02 01:53:24 -04:00
parent 0b575a3e1f
commit 345c39417b
17 changed files with 1306 additions and 17 deletions
+55
View File
@@ -0,0 +1,55 @@
"""SVG -> PDF (vector render via WeasyPrint).
SVG is XML by spec, so the document is first well-formedness-checked with
lxml — an unbalanced file (e.g. "<svg><g></path>") is a *job* error with
"Invalid SVG: <reason>", never a silent blank render (HTML5 foreign-content
parsing would otherwise swallow the mismatch and succeed with an empty page).
The SVG is then embedded verbatim in a minimal A4 HTML document; WeasyPrint
renders SVG natively as a vector (text stays sharp, no rasterization). A
forced page break guarantees at least one PDF page even for a degenerate
document. A WeasyPrint render failure is also reported as "Invalid SVG: ...".
"""
from __future__ import annotations
from pathlib import Path
from lxml import etree
from . import common
_DOC = (
"<!DOCTYPE html><html><head><style>"
"@page { size: A4; margin: 20mm; }"
"body { margin: 0; font-kerning: none; }"
"svg { max-width: 100%; height: auto; }"
"</style></head><body>{svg}<div style='page-break-after: always'></div>"
"</body></html>"
)
def convert(path: Path, job_id: str, progress_cb=None, output_dir=None,
source_name=None) -> str:
"""Render an SVG file to a vector PDF."""
raw = path.read_bytes()
if not raw.strip():
raise ValueError("empty file: nothing to convert")
svg_text = common.decode_text(raw)
try:
etree.fromstring(svg_text.encode("utf-8"))
except etree.XMLSyntaxError as exc:
raise ValueError(f"Invalid SVG: {exc}") from exc
doc = _DOC.replace("{svg}", svg_text)
out_dir = common.default_output_dir(output_dir)
common.report(progress_cb, 30.0, f"Rendering {path.name} (1/1)")
try:
pdf_bytes = common.html_to_pdf_bytes(doc)
except ValueError:
raise # empty-file errors keep their own message
except Exception as exc: # noqa: BLE001 - render failure is a job error
raise ValueError(f"Invalid SVG: {exc}") from exc
filename = common.derive_export_name(source_name or path.name, out_dir)
return common.finalize_pdf(pdf_bytes, out_dir, filename, job_id,
progress_cb=progress_cb)