Skip to content

0.19.0 — Floats, the measure/layout agreement gate, and the real-template campaign

Choose a tag to compare

@danmolitor danmolitor released this 05 Sep 12:12
· 89 commits to main since this release
90767b3

The corpus-campaign release: we rendered 15 real production invoice templates from GitHub through the engine and fixed what they exposed — the full story. Measured result: 11 of 15 render correctly, 4 degrade legibly with every cause named in warnings, 0 broken (from 3/8/4 at the start).

⚠️ Behavior change: absolute offsets anchor the margin edge

bottom/right offsets on position: absolute now position the margin edge, per CSS. Previously they anchored the border box, so any absolutely-positioned element combining a bottom/right offset with margins rendered past its anchor by the margin size. If a positioned element sits closer to the top-left after upgrading, that's the spec-correct position. (Found as a receipt footer rendering below the page bottom with only ascender tips visible — "Thk ft".)

HTML input path

  • Float support (document subset)float: left/right + clear as column rows: consecutive floated siblings form a row (the Bootstrap col-* / left-right header-pair shape). Text wrapping alongside a float remains out and warns.
  • Images size like Chrome — percent widths and max-width honored, height from the real aspect ratio, one shared sizing ladder for measurement and layout.
  • Table sections<tfoot> renders at the bottom regardless of DOM position; only the first <thead> repeats as the header; display: none now applies to rows and sections.
  • body { width: 21cm } page-sizing idiom clamps with a named warning; giant single-<tr> email layouts no longer produce blank pages; position: running() elements leave the flow per spec instead of rendering as stray text.

Engine: the measure/layout agreement gate

Six shipped bugs shared one shape — intrinsic measurement computing a height layout never produced (phantom gaps, mis-centered running headers, crushed tables). The invariant is now enforced: FORME_MEASURE_CHECK=1 flags any auto-height container whose measured height exceeds what its children occupy, and a fixture-corpus test gate fails on any emission. The gate found two of the six on its first run. All six are fixed, each with a minimal failing-first test.

Full details in engine/CHANGELOG.md and packages/*/CHANGELOG.md. All packages in lockstep at 0.19.0: npm (@formepdf/*), crates.io (forme-pdf), PyPI (formepdf), Go (v0.19.0).