PDF/UA-2 (ISO 14289-2) is now supported across the stack

PDF/UA-2 (ISO 14289-2) is now supported across the stack

May 19, 2026

The boxesandglue ecosystem now produces fully conformant PDF/UA-2 documents (ISO 14289-2:2024) on top of PDF 2.0. Every entry point into the pipeline has been wired up: the Go API, the Lua bridge, the Markdown frontend, the FO walker, and the higher-level bagme convenience library.

How to enable it

Pick the entry point that matches your workflow:

Workflow UA-1 UA-2
Markdown frontmatter format: PDF/UA format: PDF/UA-2
XSL-FO via foproc.lua bg:format="PDF/UA" on fo:root bg:format="PDF/UA-2"
glu.htmlbag.render options table format = "PDF/UA" format = "PDF/UA-2"
bagme/document.New WithPDFUA() WithPDFUA2()
xts <PDFOptions format=…> "PDF/UA" "PDF/UA-2"
Raw frontend.Document Format = FormatPDFUA Format = FormatPDFUA2

The PDF/UA-1 string is accepted everywhere PDF/UA is, so you can be explicit about the revision when both are in play.

What changes in the PDF

For PDF/UA-1 the output is unchanged in structure terms; the only on-disk difference compared to releases prior to v0.2.10 is that the redundant /Suspects false entry in MarkInfo is now omitted (it is the spec default, and the explicit entry triggered pdfinfo’s spurious “wrong type (boolean)” warning).

For PDF/UA-2 the document is genuinely PDF 2.0:

  • %PDF-2.0 header; the /Info dictionary is omitted because PDF 2.0 deprecates it in favour of XMP metadata.
  • MarkInfo is a real typed dict (/Marked true).
  • XMP carries pdfuaid:part = 2 and pdfuaid:rev = 2024.
  • StructTreeRoot has a /Namespaces array referencing two /Namespace objects:
    • http://www.w3.org/1999/xhtml (HTML5) with a complete RoleMapNS mapping each HTML5 role to its PDF 2.0 SSN equivalent.
    • http://iso.org/pdf2/ssn (PDF 2.0 Standard Structure Namespace), used for Document, Note, LBody, Lbl, L and other roles with no HTML5 counterpart.
  • Structure elements use lowercase HTML5 role names where they exist (p, h1h6, figure, table, tr, td, …).
  • Outline /Dest entries point to structure elements, not pages (PDF/UA-2 §8.8 structure destinations).

Showcases

Two minimal examples live next to each other in boxesandglue-examples/glu/xslfo:

  • 10-pdfua — PDF/UA-1 on PDF 1.7. veraPDF profile ua1: 0 failed checks.
  • 11-pdfua2 — PDF/UA-2 on PDF 2.0. veraPDF profile ua2: 0 failed checks (2352 checks pass).

Both are produced from the same FO walker (foproc.lua); only the bg:format attribute differs.

What stays compatible

UA-1 output remains a strict superset of the pre-v0.2.10 output (only the redundant /Suspects false is gone). Non-UA formats — plain PDF, PDF/A-3b (the ZUGFeRD pipeline), PDF/X-3, PDF/X-4 — are byte-identical to the previous release: the rake check task verifies all 31 in-tree examples against checked-in reference PDFs and reports byte-identical output across the board.

Reading more

  • The new mapping table and architecture notes live on the PDF/UA tagging page.
  • The Markdown-side activation is documented on the glu Markdown frontend page under “Tagged PDF (PDF/UA)”.
  • The bagme.WithPDFUA2() option and the rendered example sit on the bagme overview page.