Recent highlights
- 0.28.0: text measured and justified the way it is drawn. Content-sized text boxes (flex items, table columns) hold the shaped line they are sized for, so kerned words no longer split mid-word; justified text is justified in registered fonts too, styled runs no longer overlap when justified, and a line ending with a forced break is left unjustified as CSS specifies; Korean documents serialize in milliseconds instead of seconds. Addresses issues #181, #182 and #186. Some of these move existing documents; the changelog lists them.
- 0.27.0: text that survives copy and paste. Combining marks and shaped clusters in Arabic, Hebrew, Devanagari and Latin extract as their source text in PDF.js and Poppler, while staying valid PDF/UA and PDF/A; registered emoji fonts work as fallbacks; whitespace a font cannot encode, such as the narrow space in French amounts, no longer prints ”?”; and styled right-to-left text places numbers and Latin words where Chrome does. Addresses issues #170, #171 and #175, with fixes contributed by @amruthpillai. Some of these move existing documents; the changelog lists them.
- 0.26.0: text is drawn where it is laid out. Registered fonts (including the substitutes every PDF/UA and PDF/A document embeds) keep their kerning, justification and mark placement on the page; right-to-left text reads in the right order, with the HTML
dirattribute and CSSdirectionhonoured; ragged-right lines stay inside their boxes; and tagged output stops nesting its marked content, so files are about 5% smaller and inline link text is tagged inside its link. Fixes issues #156 to #162. Several of these move existing documents; the changelog lists them. - 0.25.0: flex geometry corrected in four places where the engine measured items by their border box and CSS measures them by their outer box, and an item taller than a fixed-height row now overflows it equally in both directions, as Chrome does.
- 0.24.0 — a flex row that crosses a page continues as parallel columns on every page it spans, wrapped rows included, instead of laying its children out one after another. A two-column layout stays two columns, and the page it starts on stops being half empty. Also the result of a systematic sweep for values the engine computed and never read: 26 of them. Six behavior changes, called out in the release notes, all of them declarations that were inert and now take effect:
max-width/min-widthon a plain text block,word-spacingas part of text measurement (lines now break where a browser breaks them),@mediaevaluated against the page content box, a stretched column painting its band on every page its row crosses, an auto-width block filling its container with itsautomargins at zero (CSS 2.1 §10.3.3), and a fixed-height box fragmenting across a page boundary instead of losing its height. - 0.23.0 — local HTML → PDF from Python with no system libraries (
pip install formepdf[local]; the output is byte-identical to@formepdf/html, CI-enforced, because it is the same Rust engine).box-sizingjoins the CSS subset — content-box is the CSS default while the engine’s fixed dimension is the border box, so a padded, borderedheightrendered short everywhere since the HTML path shipped. Also:pdfaalone now embeds the fonts-standard substitutes, which is the fix you want if you render PDF/A without also claiming PDF/UA. - 0.22.0 — PDF 2.0 output (
pdfVersion: "2.0"), PDF/A-4 and A-4f (ISO 19005-4:2020), and PDF/UA-2 (ISO 14289-2:2024), all veraPDF-gated in CI across every level. PDF/UA-2 composes with PDF/A-4 for archival and accessible on PDF 2.0. Note that PDF/A-4 is not an accessibility claim — the a/b/u split is gone. Alsoalign-items: baselinein flex rows, previously parsed and treated asflex-start. - 0.21.0 — the thirty-template library ships and gets a generated gallery; flex containers item-ize their inline children (the
<span>Label</span><span>$1,234</span>space-between row renders as two spread items, not one merged line);flex-grow/flex-shrink/flex: <n>join the HTML subset; characters no font covers report arender defect:naming the character and the remedy instead of silently printing ”?”;auditContentreaches JSX callers through@formepdf/core. Behavior changes, called out in the release notes: absolutely positioned children of a page-spanning parent anchor to the first fragment (was last, spec-incorrect); non-WinAnsi characters in styled runs reach the builtin Noto fallback; the sequential-split warning fires only on genuinely sequential outcomes and names the row; named-page documents drop trailing blank pages; margin-box decoration renders seamlessly. - 0.20.1 —
RenderHtmlResult.passesis now returned on every target and path (it was declared butundefinedon the browser/worker entries and everyrenderHtmlWithLayout); result objects are built in one shared place and the declared-type-vs-runtime shape is asserted per target in the real runtime. Output is byte-identical to 0.20.0. - 0.20.0 — the corpus campaign closes: of the 15 production templates, 14 render correctly, 1 degrades legibly with its cause named in warnings, 0 broken (what the last four taught us). New in the HTML path: attribute selectors (all seven operators + the
iflag), CSS tables on divs (the equal-height-columns idiom),rowspancolumn occupancy,body { overflow-x: hidden }as a page-level clip. Three behavior changes, called out in the release notes: half-leading (every text baseline sits half the leading lower in its line box, per the CSS line box model — line boxes and page breaks unchanged),position: fixedrenders asposition: absolute(anchored on the page where it occurs, warned), and@mediawidth measures the page box per Media Queries L4 (A4 = 794 CSS px). - 0.19.0 — the real-template campaign: floats as column rows, Chrome-matched image sizing, table-section fixes (tfoot/thead/display:none), and the measure/layout agreement gate that closed six phantom-space bugs — measured against 15 production templates from GitHub: 11 render correctly, 4 degrade legibly with named warnings, 0 broken (the full story). One behavior change:
bottom/rightabsolute offsets now anchor the margin edge per CSS — bottom/right-anchored elements with margins sit closer to the top-left, the spec-correct position. - 0.18.0 — PDF/A-3 (3b/3u/3a) and Factur-X/ZUGFeRD e-invoice containers: one render call produces the human-readable invoice PDF and embeds your EN 16931 XML as a conformant associated file, CI-validated by veraPDF and Mustangproject. Docs. Also: automatic table layout (banner-row tables no longer collapse — found by a 15-template real-world audit), a new render-defect warning channel, and warning dedup. Two corrections:
embedDataunder PDF/A-2 now errors by name (such files were never valid PDF/A-2), and tables relying on the old first-row column inference re-render correctly. - 0.17.0 — CSS Paged Media page selection:
@page :left/:rightand named pages (@page <name>+ thepageproperty) in the HTML path; CSS Grid through the HTML mapper; page-number placeholders no longer switch fonts (custom-font footers stay PDF/A-eligible); ~2× fewer allocations in large-document layout. - 0.16.0 — PDF/A-2 conformance (levels 2b, 2u, 2a), veraPDF-verified in CI, composing with PDF/UA-1. Includes a correction:
pdfaoutput from earlier versions was not valid PDF/A — re-render guidance here. - 0.15.0 — Vue 3 adapter,
@formepdf/fonts-standard, PDF/UA-1 verification as a veraPDF CI gate, and browser/Workers builds of the HTML engine. - 0.14.0 — the HTML input path:
@formepdf/html, print CSS with@page, margin boxes, and page counters. Docs. - 0.13.0 — bookmark outline fixes; the VS Code extension joined the shared version line.
@formepdf/react@0.16.0 and forme-pdf@0.16.0 (crates.io) are the same engine.