feat(docs): carry the brand fonts inside the ODT #125

Merged
peterswimm merged 1 commit from feat/udg-embed-brand-fonts into main 2026-09-11 18:37:48 +00:00
Owner

Carries the brand fonts inside generated ODT files, so documents render on-brand on machines without Sora or DM Mono installed. Follows #124.

Scope

  • tools/doc_build.pyembed_fonts() post-pass: every family an ODT's styles declare is packaged under Fonts/ and linked from svg:font-face-src, with manifest entries and the xlink namespace. --no-embed-fonts opts out. A family with no file is reported, not fatal.
  • Brand/UDG/fonts/ — Sora Regular and Bold, DM Mono Regular (TTF), each with its OFL 1.1 licence text, plus a README. Files are found by <Family without spaces>-* prefix, so adding a weight is adding a file.
  • generator/tests/unit/test_doc_build_fonts.py — new tests.

Testing

  • pytest: 298 passed, including the 7 new font tests; just check exit 0.
  • 3 failures in tools/wp_theme_ingestor/test_pipeline_invariants.py (contact.php/rituals.php blocks not in the plugin; copy coverage below its floor) also fail on main at 66f2f7e in a clean worktree without this change — pre-existing and unrelated.
  • End to end: rebuilt a 59-page proposal ODT with embedding. The three fonts are packaged byte-exact, listed in the manifest and linked from their font faces; document content is unchanged.
  • A LibreOffice that cannot see any installed font (verified: even Helvetica Neue falls back to its bundled Libertine) rendered the embedded ODT in Sora Regular and Bold, which it could only have read from the file.

Impact Statement

  • ODT output from just doc grows by about 87 KB compressed. dist/ is unchanged: fonts are embedded per document at build time, not into the 39 reference files.
  • Sora and DM Mono lack ▲ ▼ → ↔; documents using those characters still fall back to another face for them.
  • OFL 1.1 permits embedding. All vendored files set fsType 0, and a test holds that line so a restricted font can't be dropped in later.
Carries the brand fonts inside generated ODT files, so documents render on-brand on machines without Sora or DM Mono installed. Follows #124. ## Scope - `tools/doc_build.py` — `embed_fonts()` post-pass: every family an ODT's styles declare is packaged under `Fonts/` and linked from `svg:font-face-src`, with manifest entries and the `xlink` namespace. `--no-embed-fonts` opts out. A family with no file is reported, not fatal. - `Brand/UDG/fonts/` — Sora Regular and Bold, DM Mono Regular (TTF), each with its OFL 1.1 licence text, plus a README. Files are found by `<Family without spaces>-*` prefix, so adding a weight is adding a file. - `generator/tests/unit/test_doc_build_fonts.py` — new tests. ## Testing - `pytest`: 298 passed, including the 7 new font tests; `just check` exit 0. - 3 failures in `tools/wp_theme_ingestor/test_pipeline_invariants.py` (`contact.php`/`rituals.php` blocks not in the plugin; copy coverage below its floor) also fail on `main` at `66f2f7e` in a clean worktree without this change — pre-existing and unrelated. - End to end: rebuilt a 59-page proposal ODT with embedding. The three fonts are packaged byte-exact, listed in the manifest and linked from their font faces; document content is unchanged. - A LibreOffice that cannot see any installed font (verified: even Helvetica Neue falls back to its bundled Libertine) rendered the embedded ODT in Sora Regular and Bold, which it could only have read from the file. ## Impact Statement - ODT output from `just doc` grows by about 87 KB compressed. `dist/` is unchanged: fonts are embedded per document at build time, not into the 39 reference files. - Sora and DM Mono lack ▲ ▼ → ↔; documents using those characters still fall back to another face for them. - OFL 1.1 permits embedding. All vendored files set `fsType` 0, and a test holds that line so a restricted font can't be dropped in later.
feat(docs): carry the brand fonts inside the ODT
Some checks failed
PR policy check / policy-gate (pull_request) Successful in 0s
Security Scans / Gitleaks secret scan (pull_request) Successful in 49s
Security Scans / Trivy filesystem scan (pull_request) Successful in 52s
Test Generator / lint-workflows (pull_request) Successful in 47s
Test Generator / lint-prose (pull_request) Successful in 2m13s
Test Generator / test (pull_request) Failing after 2m41s
Copy coverage / Design copy reaching rendered HTML (pull_request) Failing after 1m42s
UDG dist drift gate / dist/ matches dtcg + udg sources (pull_request) Successful in 40s
be9aedb54d
A document that only names Sora renders in the viewer's default serif on
any machine without Sora installed, which is most recipients. Proven here
the hard way: a LibreOffice that cannot reach installed fonts rendered
every ODT in Linux Libertine until the fonts travelled with it.

tools/doc_build.py embeds every family an ODT's styles declare, as package
files linked from svg:font-face-src, after pandoc (as fit_images does).
Files come from Brand/UDG/fonts by name prefix, so adding a weight is
adding a file. A family with no file is reported, not fatal.
--no-embed-fonts opts out. Adds about 87 KB compressed per document.

Brand/UDG/fonts: Sora Regular and Bold, DM Mono Regular (TTF), each OFL 1.1
with its licence text. DM Mono existed in the repo only as WOFF2, which ODF
cannot embed.

Sora and DM Mono both lack the characters ▲ ▼ → ↔, which still fall back
to another face.

Tests: every declared family embedded byte-exact with manifest entries and
the xlink namespace; the package stays valid ODF; a second pass adds
nothing; a missing font is reported; every vendored TTF permits embedding
(fsType 0) and carries its licence.
peterswimm deleted branch feat/udg-embed-brand-fonts 2026-09-11 18:37:48 +00:00
Sign in to join this conversation.
No description provided.