fix: pagination measures a text box's own spacing
The atomic leaf a text box becomes carried neither its space above nor its space below, so the fit test ignored both and a page top never dropped the space above the way it does for a paragraph. The box's space rides --space-top, which the page-top decoration zeroes — the rotor centres itself in the padding box and has to follow it.
This commit is contained in:
1 parent
71ecc17a9e
commit
b134911e7b
3 files changed
+19
-9
No files matched your search
@@ -751,13 +751,22 @@ export const PageBreaks = Extension.create({
|
||||
// A text box paginates atomically: a line-split spacer can't render
|
||||
// sanely inside a rotated/floated node view.
|
||||
if (child.classList.contains('textbox-node')) {
|
||||
// Its anchor paragraph's spacing rides the box (textBox.ts): space above
|
||||
// as padding, which a page top drops, space below as the margin.
|
||||
const boxCs = getComputedStyle(child);
|
||||
const spaceAbove = parseFloat(boxCs.getPropertyValue('--space-before')) || 0;
|
||||
const dropped = spaceAbove > 0.5 && !inTableCell && parseFloat(boxCs.paddingTop) < 0.5
|
||||
? spaceAbove : 0;
|
||||
leaves.push({
|
||||
el: child,
|
||||
kind: 'atomic',
|
||||
naturalTop: naturalTopOf(child),
|
||||
naturalHeight: child.offsetHeight,
|
||||
naturalHeight: child.offsetHeight + dropped,
|
||||
spaceAfter: inTableCell ? 0 : parseFloat(boxCs.marginBottom) || 0,
|
||||
spaceAbove,
|
||||
inTableCell,
|
||||
});
|
||||
cumulativeDropped += dropped;
|
||||
continue;
|
||||
}
|
||||
// A multi-column section fragment: also atomic for spacer purposes (a
|
||||
@@ -1316,7 +1325,8 @@ export const PageBreaks = Extension.create({
|
||||
}));
|
||||
}
|
||||
for (const b of pageTopBlocks) {
|
||||
decoArray.push(Decoration.node(b.from, b.to, { style: 'padding-top:0;margin-top:0' }));
|
||||
// --space-top: a text box draws its own space above from it (textBox.ts).
|
||||
decoArray.push(Decoration.node(b.from, b.to, { style: 'padding-top:0;margin-top:0;--space-top:0px' }));
|
||||
}
|
||||
|
||||
decorations = decoArray.length > 0
|
||||
|
||||
@@ -388,11 +388,11 @@ class TextBoxView {
|
||||
// frame distance already is.
|
||||
const before = this.node.attrs.spaceBefore as number | null;
|
||||
const after = this.node.attrs.spaceAfter as number | null;
|
||||
// On the rotor too: --space-before is a registered non-inheriting property, and the
|
||||
// rotor centres itself in the padding box, so it needs the value to correct for it.
|
||||
for (const el of [d, this.rotor]) {
|
||||
if (before != null) el.style.setProperty('--space-before', `${before}pt`);
|
||||
else el.style.removeProperty('--space-before');
|
||||
// --space-top is the same value the rotor can inherit (--space-before is registered
|
||||
// non-inheriting), and it is what pageBreaks.ts zeroes at a page top.
|
||||
for (const prop of ['--space-before', '--space-top']) {
|
||||
if (before != null) d.style.setProperty(prop, `${before}pt`);
|
||||
else d.style.removeProperty(prop);
|
||||
}
|
||||
if (after != null) d.style.marginBottom = `${after}pt`;
|
||||
// Set against the middle or the far end of the column, unless the file placed the
|
||||
|
||||
@@ -387,8 +387,8 @@
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
/* Centred in the padding box, so half the space above has to come back to keep the
|
||||
frame itself below it. */
|
||||
top: calc(50% + var(--space-before) / 2);
|
||||
frame itself below it — the *applied* space, which a page top drops. */
|
||||
top: calc(50% + var(--space-top, 0px) / 2);
|
||||
box-sizing: border-box;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user