Fix Monolith and Cobalt Stripe closing-block squeeze; guard Monolith flow notes
When only the closing block moved to page 2, the page-1 deficit was shared across every gap, including the closing block's own gaps, which cannot help page 1. Page 1 then came out a few points short and the totals spilled over with the closing block. Monolith and Cobalt Stripe now squeeze only the page-1 gaps in that case, as Marble and Highlighter already do. Monolith's flow notes block could start in the last few points of a page and be cut into zero-height lines. It now holds 70 pt of room under its label first, as Marble does. Adds tests for both cases (they failed before the fix) and notes in the template specs. Fingerprint goldens and thumbnails are unchanged.
This commit is contained in:
@@ -325,13 +325,17 @@ export function planCobalt(model: RenderModel, frame: PageFrame, v: CobaltVarian
|
||||
const nominalTotal = nominalFor(tailBody);
|
||||
const overflow = nominalTotal - frame.contentHeight;
|
||||
// Everything on one page when the gaps can give back the overflow; failing that, keep the items and totals together on
|
||||
// page 1 and let only the closing block move to the next page.
|
||||
// page 1 and let only the closing block move to the next page (its own gaps stay nominal: squeezing them would take
|
||||
// a share of the deficit away from the gaps that do help page 1).
|
||||
const overflowBeforeClosing = nominalTotal - nominalClosing.h - frame.contentHeight;
|
||||
const { terms: termsRange, footer: footerRange, ...beforeRanges } = ranges;
|
||||
const slackBefore = Object.values(beforeRanges).reduce((sum, rg) => sum + rg.nominal - rg.min, 0);
|
||||
// The estimates are a hair low or high, so a page the gaps fill exactly could still spill by a fraction: keep a little air.
|
||||
const air = (over: number) => Math.min(slack, over + FIT_AIR);
|
||||
const fits = overflow > 0 && overflow <= slack ? air(overflow) : overflowBeforeClosing > 0 && overflowBeforeClosing <= slack ? air(overflowBeforeClosing) : 0;
|
||||
const deficit = Math.max(frame.heightDeficit, fits);
|
||||
const g = elastic(ranges, deficit);
|
||||
const air = (over: number, room: number) => Math.min(room, over + FIT_AIR);
|
||||
let g: Record<"client" | "table" | "tail" | "terms" | "footer", number>;
|
||||
if (overflow > 0 && overflow <= slack) g = elastic(ranges, Math.max(frame.heightDeficit, air(overflow, slack)));
|
||||
else if (overflowBeforeClosing > 0 && overflowBeforeClosing <= slackBefore) g = { ...elastic(beforeRanges, Math.max(frame.heightDeficit, air(overflowBeforeClosing, slackBefore))), terms: termsRange.nominal, footer: footerRange.nominal };
|
||||
else g = elastic(ranges, frame.heightDeficit);
|
||||
const closing = closingFor(g);
|
||||
const tailH = g.tail + tailBody;
|
||||
const table = planTable(tailH);
|
||||
|
||||
Reference in New Issue
Block a user