This release fixes issues for SREs watching stability and regressions.
✓ No known CVEs patched in this version
Topics
+7 more
Summary
AI summaryFixes selection highlight bleed‑through into headers/footers and improves inline image rendering in table cells.
Full changelog
Patch Changes
-
5fd14f9: Fix selection highlights bleeding from body into headers and footers. When body and header content shared low PM positions (because each is parsed as a separate ProseMirror document), the DOM-based selection painter matched both trees and drew phantom rectangles on every header and footer. Selection rectangles and caret lookups are now scoped to
.layout-page-content. -
11abc2d: Four header/footer fidelity follow-ups from the unification refactor:
- #379 —
RenderContext.positioningcontrols renderer outer position.renderTableFragmentandrenderParagraphFragmentnow pickposition: absolutevsposition: relativebased on context, so HF / textbox callers don't have to flip inline styles after the fact. Removes the post-renderstyle.positionflips at three call sites. - #380 — Inline-vs-inherited paragraph spacing strip.
normalizeHeaderFooterMeasureBlocksnow stripsspaceBefore/spaceAfterONLY when they were resolved from a paragraph style (e.g. Normal's default 8pt-after) and not specified inline on the HF paragraph itself. Inline<w:spacing>is preserved per ECMA-376 §17.3.1.33; previously the blanket strip collapsed intentional Word spacing. - #381 — Trailing empty paragraph after a table renders at zero height. OOXML requires a trailing block-level element after the last
<w:tbl>(the canonical convention is an empty<w:p/>). Word renders that paragraph as a zero-height anchor; we previously added~14ptof phantom space. The newsuppressEmptyParagraphHeightflag onParagraphAttrsopts the empty paragraph out of the default empty-line height fallback during measurement, while keeping the block itself for click-to-position. - #382 — Floating tables (
<w:tblpPr>) honortblpX/tblpYin headers/footers. NewresolveHeaderFooterFloatingTablePositionresolves the anchor (page/margin/text) per ECMA-376 §17.4.57 and positions the table at the requested coordinates instead of inline atcursorY. Floating tables don't advancecursorY— surrounding HF blocks flow as if the table weren't there, matching Word's no-wrap behavior.
normalizeHeaderFooterMeasureBlocksextracted into its own file to enable unit testing.Closes #379, #380, #381, #382.
- #379 —
-
0d3581d: Set package homepage to https://docx-editor.dev/.
-
4e194d7: Inline images in table cells now have visual breathing room. Previously when an image was taller than the parent paragraph's text line height, the line height was overwritten with the bare image height — so an image alone in a table cell rendered flush with the cell borders. Word treats an inline image as a tall glyph sitting on the text baseline: the image extends above the baseline (full ascent) and the line still reserves the parent font's normal descent + leading below. The line now grows to image-height + text-line-height, giving cells natural padding around image-dominant lines.
-
e12c337: Footnote rendering now routes through the body pipeline (
footnoteToProseDoc → toFlowBlocks → measureBlocks), eliminating the shadow stack infootnoteLayout.ts. Footnotes inherit the full block-kind support of the body — paragraph, table, image, textBox, fields. Pre-PR a footnote that contained a table silently dropped the table; same for inline images and PAGE/NUMPAGES fields.The fix mirrors the header/footer unification (#356/#357/#358):
- Parser:
parseFootnoteandparseEndnotenow walk all child blocks (<w:p>+<w:tbl>) in document order. TheFootnote.contentandEndnote.contenttypes widen fromParagraph[]to(Paragraph | Table)[]to match the body / HeaderFooter / TableCell shape and reflect ECMA-376 §17.11.10. - Converter: new
footnoteToProseDocnext toheaderFooterToProseDoc; takes(Paragraph | Table)[]and produces a PM doc using the sameconvertParagraphWithTextBoxes/convertTablemachinery the body uses. - Render adapter:
convertFootnoteToContentandbuildFootnoteContentMapmove fromcore/layout-bridge/footnoteLayout.tstoreact/.../PagedEditor.tsx, parallel toconvertHeaderFooterToContent. Footnote-specific presentation (default 8pt font, prepended display number as superscript) lives as a small post-process layer (applyFootnotePresentation). - Cleanup:
footnoteLayout.tsshrinks from 293 lines to ~80 — only the page-mapping helpers remain (collectFootnoteRefs,mapFootnotesToPages,calculateFootnoteReservedHeights).
Refs #378.
- Parser:
-
4aee2e0: Consolidate body-scoped
data-pm-startDOM lookups behindfindBodyPmSpans/findBodyEmptyRuns/findBodyPmAnchors/findBodyPmAnchorhelpers in@eigenpal/docx-core/layout-bridge. Removes the lingering risk that body-only operations (caret resolution, selection painting, scroll restore, imageNodeSelectionlookup, sidebar anchor positioning, visual-line navigation) accidentally match a header or footer run whose ProseMirror position collides with a body position. Same bug class as #391; this finishes the cleanup started in #406. -
274d858: Run-level OOXML attributes that were already parsed and held as ProseMirror marks now reach the painted DOM. The layout-bridge's
extractRunFormattinghad nocasearm for several run-level marks, so the visible renderer silently dropped them while the hidden ProseMirrortoDOMrendered them correctly:w:caps(§17.3.2.4) —allCaps— uppercase styling on heading runs is no longer lowercased.w:smallCaps(§17.3.2.32) —smallCaps— small-caps styling reaches the painted DOM.w:position(§17.3.2.24) — baseline shift in half-points now applies asvertical-align.w:w(§17.3.2.43) — horizontal text scale (e.g. 90% tracking on branded templates) applies as atransform: scaleX(...)on an inline-block.w:kern(§17.3.2.18) — kerning threshold gate enablesfont-kerning: normalwhen the run's font size is at or above the threshold.
The four
w:position/w:w/w:kernproperties share a single PM mark (characterSpacing) with a multi-attribute container; previously only itsspacingattribute was bridged, so the other three sat in the model unread.Refs #410.
Also propagates the cosmetic-effect marks (
emboss,imprint,textShadow,textOutline,emphasisMark) which were the same defect class — PM marks parsed correctly but the layout-bridge had nocasearm, so painted runs lost the effect. Each maps to the same CSS recipe the hidden PMtoDOMuses, so editable + painted views stay visually identical.Adjacent fix for #392: paragraph runs without an explicit
fontFamilymark now inherit the paragraph's resolved style font (from the basedOn → docDefaults cascade) instead of falling back to the painter's hardcoded Calibri stack. Same mechanism applies tofontSize— runs that don't override fall through to the paragraph's resolved default. Closes the per-run side of the rFonts cascade gap from #412.Refs #410, #412, fixes #392.
-
7ff0b6f: Fix style-cascade gaps for runs without an explicit
<w:rStyle>and tables without an explicit<w:tblStyle>. Per ECMA-376 §17.7.4.18, both should inherit from the document's default style of the same type (the one markedw:default="1"); pre-PR the default character style was skipped entirely (only docDefaults.rPr reached such runs), and the table-borders cascade was hardcoded to look up styleId"TableGrid"instead of the parsed default flag.StyleResolver.getDefaultCharacterStyle()finds the default byw:default="1"flag (varies by language: "Default Paragraph Font", "FontePadrao", "Fontepargpadro", etc.).resolveRunStyle()now applies the cascadedocDefaults.rPr → default character style → explicit character style, matching the cellMargins / paragraph cascade pattern.resolveTextFormatting()no longer short-circuits when a run has nostyleId— it always consults the full cascade.- Table borders cascade replaces the hardcoded
getStyle('TableGrid')withgetDefaultTableStyle(), matching the cellMargins cascade and working for documents whose default table style has any styleId.
5 new unit tests cover the default character style cascade and the
getDefaultCharacterStyle()helper. All 449 core tests pass (was 445).Refs #412.
-
4e194d7: Three Word-fidelity fixes surfaced by the Metal Nobre "DC_Template_Descricao_Cargo" template:
- Inline images no longer overflow their containing line. Browsers compute a non-integer height for
<img>from the natural aspect ratio when onlywidth/heightattributes are set, which clipped images sized in EMU (e.g. wp:extent1771650×278918rounds to186×29px but the natural ratio gave29.29px). Width/height are now also pinned via inline style, and the inline-image vertical alignment is the defaultbaselinerather thanmiddle—middleadds half-x-height of parent-font leading and pushed the image past the bottom of any line sized to fit just the image (the typical "image alone in a table cell" case). - Explicit
w:beforeis honored on the first paragraph of a page/column. The paginator was unconditionally zeroingspaceBeforewhenever the cursor was attopMargin, which dropped Word-authored leading space (e.g.w:before="1800"on the title paragraph). Word 2013+ honors explicit before-spacing at the top of a page; trailing-spacing is already reset on new-page so applying it here does not carry spacing across page breaks. - A hard
<w:br w:type="page"/>in an otherwise-empty paragraph now forces a page break.paragraphHasPageBreakpreviously required preceding visible content (relying onrenderedPageBreakBeforeto cover leading breaks), but that attr is informational only and not honored at layout, so an empty paragraph containing just a page-break run silently dropped the break.
- Inline images no longer overflow their containing line. Browsers compute a non-integer height for
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About Docx Editor
All releases →Related context
Related tools
Earlier breaking changes
- v@eigenpal/[email protected] Shared i18n package extracted into @eigenpal/docx-editor-i18n.
- v@eigenpal/[email protected] `showPrintButton` prop removed from `<DocxEditor>` and toolbar components.
- v@eigenpal/[email protected] Toolbar naming unified across React and Vue adapters; classic toolbar removed.
- v@eigenpal/[email protected] Agent UI components relocated to new agent packages and API changed.
- v@eigenpal/[email protected] Shared i18n package extracted from adapters into dedicated locale bundle.
Beta — feedback welcome: [email protected]