Add pagination blocks, renderCore, layout audit and react-pdf quirk tests
TableGuard, BottomSpacer, FirstPageHeader and PageChrome implement the verified pagination rules; renderCore returns bytes, a normalised layout tree, audit issues and a layout fingerprint. auditLayout detects overlaps, ink overflow, truncation, header-only pages and split blocks. Quirk tests pin the react-pdf behaviours the design depends on, and a child-process test pins the page-level absolute Svg hang.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Child-process scenarios for src/pdf/hang.test.ts. Bundled with esbuild and run with node, because
|
||||
// react-pdf's paginate() is a synchronous loop: an in-process timer never fires while it spins.
|
||||
import { createElement as h } from "react";
|
||||
import { Document, Page, Path, Svg, Text, View } from "@react-pdf/renderer";
|
||||
import path from "node:path";
|
||||
import { FirstPageHeader } from "../../src/pdf/blocks/FirstPageHeader";
|
||||
import { find } from "../../src/pdf/testing/docs";
|
||||
import { registerBundledFonts, stack } from "../../src/pdf/fonts/register";
|
||||
import { renderCore } from "../../src/pdf/render/core";
|
||||
|
||||
registerBundledFonts(path.resolve(process.cwd(), "public/fonts"));
|
||||
|
||||
const [scenario, rowsArg] = process.argv.slice(2);
|
||||
const rows = Number(rowsArg);
|
||||
const W = 595.28;
|
||||
const H = 841.89;
|
||||
const PAD = 40;
|
||||
const text = { fontFamily: stack("IBM Plex Sans"), fontSize: 10, lineHeight: "12pt" };
|
||||
|
||||
const flow = Array.from({ length: rows }, (_, i) =>
|
||||
h(View, { key: i, style: { height: 18 } }, h(Text, { style: text }, `Row ${i + 1}`)),
|
||||
);
|
||||
|
||||
const svg = (extra: Record<string, unknown>) =>
|
||||
h(
|
||||
Svg,
|
||||
{ viewBox: "0 0 100 40", style: { width: W, height: 40, ...extra } },
|
||||
h(Path, { d: "M0 0 L100 0 L100 40 L0 40 Z", fill: "#cccccc" }),
|
||||
);
|
||||
|
||||
function pageWith(children: unknown[]) {
|
||||
return h(Document, null, h(Page, { size: { width: W, height: H }, style: { padding: PAD } }, ...(children as never[])));
|
||||
}
|
||||
|
||||
const element =
|
||||
scenario === "page-level-svg"
|
||||
? // Non-fixed, absolute, full width, straddling the bottom margin line (H - PAD = 801.89).
|
||||
pageWith([...flow, svg({ position: "absolute", left: 0, top: H - PAD - 20 })])
|
||||
: pageWith([
|
||||
h(
|
||||
FirstPageHeader,
|
||||
{
|
||||
key: "head",
|
||||
pad: { top: PAD, right: PAD, bottom: PAD, left: PAD },
|
||||
decor: [{ x: 0, y: 10, width: W, height: 40, children: svg({}) }],
|
||||
style: { height: 60 },
|
||||
},
|
||||
h(Text, { style: text }, "Header"),
|
||||
),
|
||||
...flow,
|
||||
]);
|
||||
|
||||
const r = await renderCore(element);
|
||||
const svgPages = r.layout.map((p) => find(p, (n) => n.type === "svg").length);
|
||||
console.log(JSON.stringify({ pages: r.pages, svgPages }));
|
||||
Reference in New Issue
Block a user