80 lines
3.9 KiB
Markdown
80 lines
3.9 KiB
Markdown
# REPORT-20260829-1300-pdf — mopac-pdf v0 (Redmine 499)
|
|
|
|
Status: DONE. ukrrs/mopac-pdf created (Gitea API/tea), seeded AGPLv3,
|
|
implemented, tested, smoked, pushed to `main`
|
|
(https://git.knownelement.com/ukrrs/mopac-pdf). Clone at
|
|
`~/projects/meta/MOPAC/pdf`.
|
|
|
|
## Engine decision: typst (digest-pinned), pandoc+LaTeX rejected
|
|
|
|
Full rationale + measurements committed as `docs/ENGINE-DECISION.md` in
|
|
the repo. Summary, measured 2026-08-29 on identical content (TOC + table +
|
|
chart figure):
|
|
|
|
| | typst 0.15.1 | pandoc 3.5 + xelatex |
|
|
|---|---|---|
|
|
| compile | 0.94 s | 7.66 s (~8x slower) |
|
|
| image | ~200 MB | 758 MB |
|
|
| templates | typed functions, `#show: report.with(...)` | LaTeX preamble/class surgery, multi-pass TOC |
|
|
| output | modern typography out of the box | classic LaTeX look |
|
|
|
|
typst also natively streams `compile doc.typ -` to stdout, which keeps our
|
|
engine layer pure bytes-in/bytes-out (no root-owned files, no temp
|
|
collisions). Supply chain per Charles' clarification: prebuilt Rust binary
|
|
in a digest-pinned image is tooling; OUR code is Go only.
|
|
Pin: `ghcr.io/typst/typst@sha256:032e292...9c4c422f` (= 0.15.1,
|
|
cross-checked), run `--network none` with a private `/work` root.
|
|
|
|
## What shipped (v0)
|
|
|
|
- CLI `mopac-pdf`: markdown + front-matter (title/subtitle/author/date/
|
|
classification/template) -> PDF to stdout or `-o`; `-t`/`-T` template
|
|
pick/override (templates embedded in the binary AND loadable from a
|
|
dir); `-pages` helper; exit codes 0 ok / 1 usage-input / 2 engine.
|
|
- Templates: `report` (title page, TOC, numbered headings, running header,
|
|
page X/Y + classification footer) and `brief` (dense 1-3 pager, compact
|
|
title block, classification badge, small tables).
|
|
- Markdown subset the whole stack actually emits: headings, paragraphs,
|
|
inline bold/italic/code/links, ul/ol, blockquotes, hr, GFM tables with
|
|
alignment, fenced code, block images.
|
|
- Charts: fenced ```chart data blocks -> bar charts rendered PURE GO
|
|
(vendored go-chart, MIT) -> PNG figures. One type proven end to end,
|
|
per v0 scope.
|
|
- Dev in docker only: `dev.sh`/`make` route through the family builder
|
|
digest; deps vendored (hermetic); smoke drives the REAL typst container
|
|
from the host (11 checks: both templates, stdin/stdout, page counts,
|
|
exit codes, custom template dir — all green).
|
|
- Tests: 7 packages ok — front-matter table tests, parser tests, golden
|
|
.md -> .typ fixtures (drift-catching), chart PNG decode, tiny
|
|
/Pages /Count parser tests, engine argv contract via stub docker, CLI
|
|
flag/exit-code matrix.
|
|
|
|
## Sample outputs (local, regenerable via ./dev.sh smoke)
|
|
|
|
- ~/projects/meta/MOPAC/pdf/out/sample-report.pdf — 4 pages (title, TOC, body + table + chart)
|
|
- ~/projects/meta/MOPAC/pdf/out/sample-brief.pdf — 1 page (dense exec brief)
|
|
- ~/projects/meta/MOPAC/pdf/out/stdin-report.pdf — stdin->stdout path
|
|
- fixtures live in-repo: testdata/sample-{report,brief}.md (+ .typ.golden)
|
|
|
|
## How the briefing pipeline will call it
|
|
|
|
The COS briefing/harness side already speaks markdown; the contract here
|
|
is a single exec: `mopac-pdf -o <path>.pdf <brief.md>` (or pipe bytes:
|
|
`mopac-pdf < brief.md > brief.pdf`). Front-matter carries the identity
|
|
(title/date/classification/template=brief for the 0630 morning brief,
|
|
report for long-form), so callers never touch typst. Failure semantics
|
|
are harness-shaped: 0/1/2, engine stderr surfaced verbatim, no partial
|
|
output files on failure. Engine image + docker binary overridable by env
|
|
for canary/migration. No daemon, no state — a pure function, safe to call
|
|
from any loop turn.
|
|
|
|
## Next (proposals, not started)
|
|
|
|
- More chart types (line, donut) — renderer is a one-function extension
|
|
point; needs a data-block convention for series.
|
|
- More templates: letterhead, invoice, slide-deck-ish landscape.
|
|
- Nested lists >1 level; footnotes; typst-side escape hardening fuzz.
|
|
- Optional direct embedding of briefing charts without PNG round-trip
|
|
(emit typst vector drawing for crisp print) once typst scripting
|
|
surface stabilizes.
|