Skip to content

feat(docrender): bundle nasa, ieee and acm themes and fix the PDF default font stack - #561

Merged
HuiJun merged 9 commits into
developfrom
feature/document-convention-themes
Sep 24, 2026
Merged

HuiJun merged 9 commits into
developfrom
feature/document-convention-themes

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #560; merge that first.

What and why

Two faults in the PDF form of -render-document, and three new themes on top of the fix.

The PDF default was set in DejaVu. internal/doc/docpdf/print.css asked for bare serif, sans-serif and monospace. fontconfig resolves those to DejaVu on most Linux machines (fc-match serif → DejaVu Serif), a face some 15 % wider and taller than Times at the same nominal size, so an 11pt page read like 13pt — while the Times-metric Liberation Serif installed beside it was never chosen because nothing named it. The default stacks now name the conventional families first, their metric-compatible free equivalents next and the generic family last:

--sysml-font-body:    "Times New Roman", Times, "Liberation Serif", "Nimbus Roman", serif;
--sysml-font-heading: Arial, Helvetica, "Liberation Sans", "Nimbus Sans", sans-serif;
--sysml-font-mono:    "Courier New", Courier, "Liberation Mono", "Nimbus Mono PS", monospace;

The same stacks go into pandoc.css (body, headings, code and the page-number footer, which was the one place DejaVu still leaked through). Page size, margins and every point size are unchanged; the HTML sheet keeps system-ui, a system face being the deliberate default for a page.

A theme could not govern the PDF page. print.css sits in @layer opensysml-print, declared after the theme's opensysml layer, so its --sysml-font-size: 11pt, faces and heading scale won over any theme's. Rendering -html-theme report -doc-form pdf on develop confirmed it: /BaseFont DejaVu Serif, body 11pt — the theme's Charter/Georgia stack and 1.0625rem body never reached the page. The fix is a print companion: a theme may carry themes/<name>.print.css, one block of @layer opensysml-print-theme, which print.css declares after its own layer (@layer opensysml-print, opensysml-print-theme;) and which docpdf.htmlOptions inlines right after the print sheet through the new docrender.ThemePrintStylesheet(name). A companion writes :root page tokens, @page rules and page-margin boxes, and .sysml-document tokens, so it controls page geometry, typography, captions, tables, heading scale and the page-number footer. Themes() filters companions out of the public list and ThemeStylesheet refuses their names. The cascade for an HTML-input engine is

default sheet + theme (opensysml) < print sheet (opensysml-print) < theme's companion (opensysml-print-theme) < KaTeX < reader's -html-css, unlayered

-html-no-default-css leaves the default sheet, the print sheet and the companion out together; the pandoc engine still refuses -html-theme and -html-no-default-css with the typed unsupported-option error. print and report gain companions carrying the tokens their sheets already set, so what they always meant for paper now prints.

Three convention themes, nasa, ieee and acm, each a <name>.css plus <name>.print.css. All three are black on white (--sysml-text, --sysml-accent, --sysml-rule black, --sysml-surface transparent), rule tables with thin horizontal lines only, title tables above and caption figures below, set code in Courier/Liberation Mono, leave the measure unconstrained on paper, and set the same faces and point sizes on screen as on paper so a page and its PDF agree. The public theme list is default, acm, ieee, modern, nasa, print, report.

Theme Convention and sources Verified values set Choices where the convention is silent
nasa NASA STI Report Series — NASA Publications Guide for Authors (NASA/SP-2005-7602, NTRS 20050189209, § 4.3.1.7) and NASA Scientific and Technical Information Standards (NTRS 20060049392, § 1.3.1.2, § 1.3.1.4, figure/table chapters) Serif text, sans titles/figure text/tables; Times, Arial, Courier; 12pt body (11–12pt recommended, never below 10pt); 8½ × 11 in; figures centred with caption centred below; captions at text size; front matter in lowercase roman with the title page as unnumbered page i, body in arabic; headings never left alone at a page foot Bold sans 14/12/12pt headings (sizes live in the STI Word templates, not the text); 1 in margins; line height 1.25; 24pt bold sans title on the existing title-page block; page number centred in the bottom margin at body size. Roman front matter via named pages: title page cover (unnumbered), contents front (lower-roman), first body page resets the counter to 1
ieee IEEE Transactions — IEEE Editorial Style Manual for Authors; IEEE PES Preparation of a Formatted Transactions/Journal Paper 8½ × 11 in; ~0.67 in margins; Times throughout; 10pt body and equations; 8pt captions, tables, footnotes, references; 24pt title; primary heads centred small caps, subheads italic; full justification; 1 pica indent Arabic section numbers kept (see limits); line height 1.2; page number centred at 8pt
acm ACM Primary Article Template (acmart), https://www.acm.org/publications/proceedings-template Libertine family with Times/Liberation fallback ("Libertinus Serif", "Linux Libertine O", "Linux Libertine", "Times New Roman", "Liberation Serif", serif; sans "Libertinus Sans", "Linux Biolinum O", "Linux Biolinum", Arial, Helvetica, "Liberation Sans", sans-serif); 10pt body; letter page; numbered bold sans headings; 9pt captions in the body face; single-column acmsmall/manuscript styles exist 1 in margins; line height 1.2; 10pt paragraph indent; 17pt bold sans title as acmart sets it; 9pt tables and page numbers

Docs: docs/reference/cli.md (flag row, theme list, layer order), docs/manual/outputs.md (theme table, three-layer cascade), docs/project/html-document-backend.md (new Bundled themes section with the sources and choices above, the companion mechanism, the limits), cmd/sysml/usage.go and the regenerated packaging/man/man1/sysml.1. Changelog fragments document-convention-themes.added.md and pdf-default-font-stack.fixed.md.

Known limits

  • Single column for ieee and acm. IEEE Transactions are two 3.5 in columns; migrated tables and wide diagrams do not fit one, so ieee is a single-column manuscript of a two-column journal. ACM's acmsmall/manuscript styles are single-column, so acm is a layout ACM itself publishes.
  • No Roman-numbered IEEE section heads. The renderer writes each section number as text in sysml-section-number and the contents list repeats it, so CSS can neither restyle that text as roman nor replace it with a counter without hiding the number the markup carries. ieee keeps arabic numbers rather than faking roman ones.
  • NASA covers stop at the title. Report number, authors and affiliations, issuing centre and the SF-298 page are not in the document IR; nasa styles the existing title-page block and invents nothing. Its roman front matter covers the pages the markup can name (title page, contents); a render without -doc-title-page/-doc-toc simply has fewer of them.
  • Libertine is rarely installed. acm falls through to Times metrics (Liberation Serif on Linux) where it is absent — the documented fallback, as the evidence below shows.
  • Prince is not in the toolchain, so its installed tests skip as before; WeasyPrint and pandoc were exercised.

Specification basis

Not a SysML behaviour change; no row of docs/project/spec-compliance.md moves. The typographic values are those the sources named above state, and each value not stated by a source is recorded as a choice in docs/project/html-document-backend.md.

How it was verified

New and updated tests:

  • internal/doc/docrender/html_test.go — Themes() lists the seven themes and no .print.css companion; ThemePrintStylesheet returns a companion for acm, ieee, nasa, print, report, none for default/modern, an error for an unknown name; each companion is one @layer opensysml-print-theme block whose selectors are :root, .sysml-document… or @page; each convention theme sets its font stacks, body size, caption/table sizes, page size and margin, black-on-white tokens and thin horizontal rules; -html-default-css output never contains a companion.
  • internal/doc/docpdf/docpdf_test.go — fake-tool test pins the page handed to WeasyPrint: @layer opensysml → theme sheet → @layer opensysml-print → companion inlined whole → KaTeX link → reader inline → reader link, each once, and NoDefaultStylesheet drops every bundled sheet while keeping the reader's; the print sheet contract test expects @layer opensysml-print, opensysml-print-theme;.
  • internal/doc/docpdf/integration_test.go — TestRenderThemesWithInstalledEngines renders the telescope fixture and a prose fixture under the default and each theme, and reads back from the PDF bytes (Go only, flate streams inflated): MediaBox (A4 vs letter), /BaseFont names (Times/Arial/Courier-compatible, no DejaVu) and the dominant text size (11/11/12.8/12/10/10pt). A control renders the generic-family stack and asserts DejaVu does appear, so the check is load-bearing. Pandoc is asserted to refuse -html-theme with the typed error.
  • cmd/sysml/render_document_html_test.go — invalid-theme message lists all seven.

Gates, all clean: go build ./..., go vet ./..., gofmt -l . (empty), go test ./..., make lint, make docs-check (links, doc-ids, figures, changelog, census), make man && make man-check, and

OPENSYSML_REQUIRE_PDF_TOOLCHAIN=1 go test -count=1 -run Installed ./internal/doc/docpdf
ok   github.com/Open-MBEE/OpenSysML/internal/doc/docpdf   45.048s   (36 passing subtests; prince skipped as unavailable)

Evidence

Observatory::MassReport rendered from internal/doc/docrender/testdata/telescope_report.sysml (telescope) and docs/manual/examples/observatory.sysml (worked example) with -pdf-title-page -pdf-toc -pdf-number-sections, read back with pypdf. "Body size" is the size most extracted glyphs are set at; for the telescope fixture under ieee that is the 8pt of its many tables and captions (paragraph text is 10pt, 634 glyphs against 728), and for report 12.8pt is 1.0625rem at the 12pt root.

Render MediaBox (in) Body size /BaseFont (subset prefixes stripped)
telescope, default, before (develop) 8.27 × 11.69 11pt DejaVu-Serif, DejaVu-Serif-Bold, DejaVu-Serif-Italic, DejaVu-Sans-Bold, DejaVu-Sans-Mono, Liberation-Sans
telescope, report, before (develop) 8.27 × 11.69 11pt DejaVu-Serif, DejaVu-Serif-Bold, DejaVu-Serif-Italic, DejaVu-Sans-Bold, Liberation-Sans, Liberation-Mono
telescope, default, after 8.27 × 11.69 11pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
telescope, nasa 8.5 × 11 12pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
telescope, ieee 8.5 × 11 10pt paragraphs (8pt tables/captions dominate) Liberation-Serif, -Bold, -Italic, -Small-Caps, Liberation-Sans, Liberation-Mono
telescope, acm 8.5 × 11 10pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
telescope, report 8.27 × 11.69 12.8pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Mono
worked example, default, before 8.27 × 11.69 11pt DejaVu-Serif, DejaVu-Serif-Bold, DejaVu-Serif-Italic, DejaVu-Sans-Bold, DejaVu-Sans-Mono, Liberation-Sans
worked example, default, after 8.27 × 11.69 11pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
worked example, nasa 8.5 × 11 12pt Liberation-Serif, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
worked example, ieee 8.5 × 11 10pt Liberation-Serif, -Bold, -Italic, -Small-Caps, Liberation-Sans, Liberation-Mono
worked example, acm 8.5 × 11 10pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Sans-Bold, Liberation-Mono
worked example, report 8.27 × 11.69 12.8pt Liberation-Serif, -Bold, -Italic, Liberation-Sans, Liberation-Mono

The nasa PDF's footers read (title page) nothing, (contents) ii, (body) 1, 2, 3 — checked with pdftotext page by page.

First two pages of the telescope fixture (pypdfium2, scale 1.3):

Default, before:

telescope default before

Default, after:

telescope default after

nasa:

telescope nasa

ieee:

telescope ieee

acm:

telescope acm

report:

telescope report

HTML output of the same fixture in Chrome, so screen and paper agree (nasa 12pt Times-compatible body with bold sans heads; ieee 10pt body, centred small-caps heads, 8pt tables and captions; acm 10pt body in the Times-metric fallback, bold sans heads, 9pt captions):

nasa:

telescope nasa html

ieee:

telescope ieee html

acm:

telescope acm html

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

devin-ai-integration Bot and others added 4 commits September 24, 2026 05:23
… families

The print and pandoc stylesheets asked for bare serif, sans-serif and
monospace, which fontconfig resolves to DejaVu on most Linux machines while
the Times-metric Liberation faces installed beside it go unchosen. The default
body, heading, code and page-number stacks now name the conventional families,
their metric-compatible free equivalents and the generic family last. Sizes,
margins and page size are unchanged; print.css also declares the
opensysml-print-theme layer a theme's print companion fills.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
A theme may carry themes/<name>.print.css, laid by the PDF backend over its
print sheet in the opensysml-print-theme layer so the theme's page size,
margins, faces, body size, heading scale and footer reach paper. Themes()
leaves companions out of the public list. nasa, ieee and acm follow the NASA
STI, IEEE Transactions and ACM acmart conventions; print and report gain
companions so their print faces and sizes now print.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Usage text, manual page, CLI reference, outputs manual and the backend design
note name every bundled theme, the print-companion cascade order, the sources
and choices behind nasa, ieee and acm, and their limits; changelog fragments
for the themes and the default font stack.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Theme discovery lists the seven themes and no companion; each convention
theme's tokens are asserted; a fake-tool test pins default/theme, print sheet,
companion, KaTeX, reader order and that -html-no-default-css drops every
bundled sheet; installed-toolchain tests read /BaseFont, MediaBox and the body
size back from the PDF for the default and each theme.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

…onvention-themes

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	internal/doc/docpdf/integration_test.go
#	internal/doc/docrender/html_test.go
@devin-ai-integration
devin-ai-integration Bot changed the base branch from develop to feature/positioned-label-fitting September 24, 2026 06:34
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 24, 2026 10:13
devin-ai-integration[bot]

This comment was marked as resolved.

…n without a title page

The acm theme documented 9pt tables but sized only the landscape wide-table
path; an ordinary table stayed at the 10pt body. A --sysml-table-font-size
token now applies to every acm table in HTML and PDF.

The nasa companion reset the page counter on the first main page, which was
the bare title heading when a contents list was asked for without a title
page: the title counted 1, the contents ii and the body continued at 3. The
title heading leading a contents list now shares its front page, and the
article itself is the main page, so running text ahead of the first section
opens the body at 1.

Installed-toolchain tests read the table size back under each convention
theme and the footer sequence back from a nasa report under every
title-page and contents combination.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…ptions in the convention's face

The nasa companion kept the page counter for the front matter and reset
it on the first main page, so a body opening on a landscape wide page
printed the physical page number and the next portrait page restarted at
1. The cover and front pages now leave the page counter at 0 and count in
roman on a front counter, so the body opens at 1 whichever named page it
starts on. nasa table captions take the sans face like the rest of the
table; acm captions take the text face acmart sets them in.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Base automatically changed from feature/positioned-label-fitting to develop September 24, 2026 13:31
@HuiJun
HuiJun merged commit a10b424 into develop Sep 24, 2026
15 checks passed
@HuiJun
HuiJun deleted the feature/document-convention-themes branch September 24, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant