diff --git a/docs/architecture/tables.md b/docs/architecture/tables.md index 8bdc4df..ed4b903 100644 --- a/docs/architecture/tables.md +++ b/docs/architecture/tables.md @@ -88,3 +88,15 @@ We deliberately keep TipTap's `resizable: false` (so its own columnResizing plug schematic text line (`previewTextCss`: thickness = bold, slant = italic, colour = the region's): without it an emphasis-only area such as first/last column or the total row is **invisible** in a tile, since the tiles hold no real text — only fills and borders would show. + +## Cell metrics measured against LibreOffice + +- **No space above a cell's first block.** LibreOffice adds none there (its + `AddParaTableSpacingAtStart`); Word does, so `editor.css` drops it for the `add` spacing + model only. Measured on the Math Guide: the table row grew 1mm per row without it. `pageBreaks.ts` + excludes cell leaves from its page-top-drop detection, or that missing padding would read + as a decoration to add back. +- **`` carries no UA defaults.** A repeating ODF header row (`table:table-header-rows`) + becomes a `tableHeader`, and the browser centres and bolds it — neither Word nor LibreOffice + does. `editor.css` resets both, so the cell follows its own style (the "header row" preset's + bold still comes from `.cell-header`). diff --git a/src/lib/editor/extensions/pageBreaks.ts b/src/lib/editor/extensions/pageBreaks.ts index f12a48d..94639e4 100644 --- a/src/lib/editor/extensions/pageBreaks.ts +++ b/src/lib/editor/extensions/pageBreaks.ts @@ -807,8 +807,10 @@ export const PageBreaks = Extension.create({ const cs = getComputedStyle(child); // The block's own space above, and how much of it the last pass took off // at a page top (the decoration zeroes both padding and margin). + // A cell's first block never carries it (LibreOffice adds none there), so + // the missing padding is the document, not a decoration to add back. const spaceAbove = parseFloat(cs.getPropertyValue('--space-before')) || 0; - const dropped = spaceAbove > 0.5 + const dropped = spaceAbove > 0.5 && !inTableCell && parseFloat(cs.paddingTop) < 0.5 && parseFloat(cs.marginTop) < 0.5 ? spaceAbove : 0; leaves.push({ diff --git a/src/styles/editor.css b/src/styles/editor.css index 24ad546..3efab67 100644 --- a/src/styles/editor.css +++ b/src/styles/editor.css @@ -487,6 +487,12 @@ padding-top: 0; margin-top: var(--space-before); } +/* LibreOffice adds no space above the first block of a table cell (measured; its + AddParaTableSpacingAtStart), Word does — so it follows the document's spacing model. */ +.paper:not([data-spacing-model='max']) .tiptap :is(td, th) > :first-child { + padding-top: 0; + margin-top: 0; +} /* The line box: the paragraph's spacing factor times its font's natural line height. Either half may come from the style rule or, nearer, from the block's own attrs @@ -636,6 +642,10 @@ border: 1px solid #000; padding: var(--cell-pad, 0 0.19cm); vertical-align: top; + /* A repeating header row is a , and no word processor centres or bolds its text + for that reason — drop the two UA defaults so the cell follows its own style. */ + text-align: inherit; + font-weight: inherit; /* Positioning context for the column-resize handle widget (a child div the resize plugin places at the cell's right edge). */ position: relative;