Skip to content

v0.22.0

Choose a tag to compare

@danmolitor danmolitor released this 10 Sep 02:59
· 116 commits to main since this release
fb37972

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.0 header, 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-Document structure tree in the 2.0 namespace, ISO 32005 containment (grouping elements' own ink is tagged artifact), graphics as /Figure with a barcode/QR's encoded data as /ActualText when no alt is given, ListNumbering, structure destinations for outlines and internal links. Composes with pdfa: "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: baseline in flex rows — previously parsed and treated as flex-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-spacing and word-spacing now inherit, as CSS specifies. Tracking declared on a container finally reaches its children.
  • flex: <n> is spec-correct — it now sets flex-basis: 0 (CSS: flex: 1 = 1 1 0), not basis: auto. A flex: 1 text 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: 33 view 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.