From 80e935145b23cfa50976f6b2c27bcda60443fa5a Mon Sep 17 00:00:00 2001 From: Steffen Becker Date: Mon, 10 Aug 2026 20:46:35 +0000 Subject: [PATCH] fix: keep-with-next reserves a successor that cannot split MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A paragraph with fewer lines than orphan and widow control demand together has no legal break point, so it moves to the next page whole — and the heading kept with it has to follow. Measuring only its first two lines left the heading stranded at the page foot. --- src/lib/editor/extensions/pageBreaks.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/editor/extensions/pageBreaks.ts b/src/lib/editor/extensions/pageBreaks.ts index 9f2dcd0..9a5e0b2 100644 --- a/src/lib/editor/extensions/pageBreaks.ts +++ b/src/lib/editor/extensions/pageBreaks.ts @@ -511,8 +511,10 @@ export const PageBreaks = Extension.create({ function firstLinesHeight(el: HTMLElement, scale: number, want: number): number { const lines = getLineRects(el); if (!lines.length) return el.offsetHeight; - const last = lines[Math.min(want, lines.length) - 1]; - return (last.bottom - lines[0].top) / scale; + // A block with fewer lines than orphan and widow control demand together has + // no legal split point at all, so the pair needs room for the whole of it. + const keep = lines.length < want * 2 ? lines.length : want; + return (lines[keep - 1].bottom - lines[0].top) / scale; } function findLineSplit(