v0.22.0
A minor with major conformance surface and called-out behavior changes. All packages share the line: engine (crates.io forme-pdf), every @formepdf/* npm package (@formepdf/preview joins the line this release), formepdf (PyPI), forme-go (tag v0.22.0), and the VS Code extension.
Added
- PDF 2.0 output —
pdfVersion: "2.0"writes ISO 32000-2:%PDF-2.0header, XMP metadata always, no trailer/Info, and every font must be embedded (32000-2 removes the standard-14 provision; base-14 output errors by name with the fonts-standard remedy). The default"1.7"path is byte-identical to 0.21.0, asserted by pin. - PDF/A-4 and PDF/A-4f (ISO 19005-4:2020) —
pdfa: "4" | "4f", implying PDF 2.0. A-4f requires at least one embedded file (an empty claim is itself non-conformant and is refused); base A-4 refuses attachments. Note: PDF/A-4 is not an accessibility claim — the a/b/u split is gone; accessibility is PDF/UA-2 territory. - PDF/UA-2 (ISO 14289-2:2024) —
pdfUa2, the PDF 2.0 accessibility claim: single-Documentstructure tree in the 2.0 namespace, ISO 32005 containment (grouping elements' own ink is tagged artifact), graphics as/Figurewith a barcode/QR's encoded data as/ActualTextwhen no alt is given,ListNumbering, structure destinations for outlines and internal links. Composes withpdfa: "4"/"4f"for archival + accessible on PDF 2.0; contradictory claims are refused by name. All of the above is veraPDF-gated in CI over the standing corpus — every level of PDF/A (2b/2a/3b/3a/4/4f), PDF/UA-1 on the 1.7 levels, PDF/UA-2 composed on the 2.0 levels. align-items: baselinein flex rows — previously parsed and treated asflex-start.- Claim-parity guards — the document-level conformance claims (
tagged,pdfa,pdfVersion,pdfUa,pdfUa2) are asserted at compile time across all five authoring adapters (react, preact, svelte, vue, and the shared markup parser), so a claim can no longer reach serialization without reaching the prop types users compile against.
Behavior changes
- Baselines use real font metrics. Text ink sits where a browser puts it: ascent/descent from the font's own metrics with half-leading, replacing font-size-as-ascent. Every baseline moves by a small per-font delta (~0.15em for Arial-class metrics); line boxes, element geometry, page breaks, and page counts are unchanged. Single glyphs centered by the line-height idiom now center exactly.
letter-spacingandword-spacingnow inherit, as CSS specifies. Tracking declared on a container finally reaches its children.flex: <n>is spec-correct — it now setsflex-basis: 0(CSS:flex: 1=1 1 0), notbasis: auto. Aflex: 1text column no longer brings its full unwrapped width to distribution and crushes fixed-width siblings.- Intrinsic widths are honest — explicit fixed widths and flex gaps now count in intrinsic measurement (an empty
width: 33view measured 0 before). Auto-sized layouts whose contents carry fixed-width boxes or gaps get their true size. - AcroForm dictionaries no longer set
/NeedAppearances— Forme authors every widget appearance stream itself, so field rendering is now identical across viewers instead of viewer-dependent.
Per-package detail in each package's CHANGELOG.md.