@broadpaper/forme 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/style.ts","../src/vnode.ts","../src/svg.ts","../src/watermark.ts","../src/measure.ts","../src/editor.ts","../src/api.ts","../src/paged.ts","../src/clip.ts"],"sourcesContent":["/**\n * Translates the inline CSS our block renderers emit into Forme's style model.\n *\n * BroadPaper blocks produce a deliberately small, self-generated CSS vocabulary\n * (we never accept CSS from users), which is what makes a faithful mapping\n * possible at all. Anything outside that vocabulary is reported rather than\n * dropped silently — the caller surfaces it as a validation warning.\n */\n\n/** CSS pixels at 96 dpi → PDF points at 72 dpi. */\nexport const PX_TO_PT = 72 / 96;\n\nexport function pxToPt(px: number): number {\n return Math.round(px * PX_TO_PT * 1000) / 1000;\n}\n\nexport interface FormeStyle {\n [prop: string]: unknown;\n}\n\nexport interface StyleTranslation {\n style: FormeStyle;\n /** CSS declarations with no Forme equivalent, e.g. \"box-shadow\". */\n unsupported: string[];\n}\n\n/** Parses an inline style string or object into kebab-case declarations. */\nexport function parseDeclarations(style: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (!style) return out;\n if (typeof style === \"object\") {\n for (const [k, v] of Object.entries(style as Record<string, unknown>)) {\n if (v === undefined || v === null || v === \"\") continue;\n out[kebab(k)] = String(v);\n }\n return out;\n }\n for (const decl of String(style).split(\";\")) {\n const i = decl.indexOf(\":\");\n if (i < 0) continue;\n const k = decl.slice(0, i).trim();\n const v = decl.slice(i + 1).trim();\n if (k && v) out[k] = v;\n }\n return out;\n}\n\nfunction kebab(s: string): string {\n return s.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n}\n\n/** \"12px\" → 9 (pt); \"50%\" → \"50%\"; \"auto\" → undefined. */\nexport function length(value: string): number | string | undefined {\n const v = value.trim();\n if (v === \"auto\" || v === \"none\" || v === \"inherit\") return undefined;\n if (v.endsWith(\"%\")) return v;\n const n = Number.parseFloat(v);\n if (!Number.isFinite(n)) return undefined;\n if (v.endsWith(\"em\")) return undefined; // resolved against font size we do not track here\n return pxToPt(n);\n}\n\nfunction num(value: string): number | undefined {\n const n = Number.parseFloat(value);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/** Normalises a CSS colour to `#rrggbb` / `rgba()` that Forme's parser accepts. */\nexport function colour(value: string): string | undefined {\n const v = value.trim().toLowerCase();\n if (!v || v === \"transparent\" || v === \"none\" || v === \"inherit\" || v === \"currentcolor\") return undefined;\n return v;\n}\n\nconst EDGE_ORDER = [\"top\", \"right\", \"bottom\", \"left\"] as const;\n\n/** \"4px 8px\" → { top: 3, right: 6, bottom: 3, left: 6 } in points. */\nexport function edges(value: string): { top: number; right: number; bottom: number; left: number } | undefined {\n const parts = value.trim().split(/\\s+/).map((p) => length(p));\n if (parts.some((p) => typeof p !== \"number\")) return undefined;\n const n = parts as number[];\n const [t, r, b, l] = n.length === 1 ? [n[0]!, n[0]!, n[0]!, n[0]!] : n.length === 2 ? [n[0]!, n[1]!, n[0]!, n[1]!] : n.length === 3 ? [n[0]!, n[1]!, n[2]!, n[1]!] : [n[0]!, n[1]!, n[2]!, n[3]!];\n return { top: t, right: r, bottom: b, left: l };\n}\n\n/** \"1px solid #E2E5EA\" → { width, style, colour }. */\nexport function border(value: string): { width: number; colour?: string } | undefined {\n const v = value.trim();\n if (!v || v === \"none\" || v.startsWith(\"0 \") || v === \"0\") return undefined;\n const widthMatch = /(-?[\\d.]+)px/.exec(v);\n const colourMatch = /(#[0-9a-f]{3,8}|rgba?\\([^)]+\\))/i.exec(v);\n const width = widthMatch ? pxToPt(Number(widthMatch[1])) : 0.75;\n if (/\\bnone\\b/.test(v)) return undefined;\n return { width, colour: colourMatch ? colourMatch[0] : undefined };\n}\n\nconst FLEX_DIRECTION: Record<string, string> = { row: \"row\", column: \"column\", \"row-reverse\": \"row-reverse\", \"column-reverse\": \"column-reverse\" };\nconst JUSTIFY: Record<string, string> = { \"flex-start\": \"flex-start\", start: \"flex-start\", \"flex-end\": \"flex-end\", end: \"flex-end\", center: \"center\", \"space-between\": \"space-between\", \"space-around\": \"space-around\", \"space-evenly\": \"space-evenly\" };\nconst ALIGN: Record<string, string> = { \"flex-start\": \"flex-start\", start: \"flex-start\", \"flex-end\": \"flex-end\", end: \"flex-end\", center: \"center\", stretch: \"stretch\", baseline: \"baseline\" };\nconst TEXT_ALIGN: Record<string, string> = { left: \"left\", right: \"right\", center: \"center\", justify: \"justify\" };\n\n/** Declarations we knowingly ignore because they have no bearing on PDF output. */\nconst IGNORED = new Set([\n \"box-sizing\", \"-webkit-font-smoothing\", \"text-rendering\", \"font-variant-numeric\", \"pointer-events\",\n \"user-select\", \"cursor\", \"text-overflow\", \"white-space\", \"word-wrap\", \"overflow-wrap\", \"box-decoration-break\",\n \"-webkit-box-decoration-break\", \"text-underline-offset\", \"text-decoration-thickness\", \"outline\", \"transition\",\n \"list-style\", \"border-collapse\", \"border-spacing\", \"table-layout\", \"vertical-align\", \"min-width\", \"max-width\",\n \"-webkit-line-clamp\", \"-webkit-box-orient\", \"object-fit\", \"content\", \"zoom\", \"transform-origin\"\n]);\n\n/**\n * Maps CSS declarations to Forme style props. Returns the props plus any\n * declaration we could not represent.\n */\nexport function translateStyle(css: Record<string, string>): StyleTranslation {\n const s: FormeStyle = {};\n const unsupported: string[] = [];\n const set = (k: string, v: unknown) => {\n if (v !== undefined) s[k] = v;\n };\n\n for (const [prop, raw] of Object.entries(css)) {\n const value = raw.trim();\n if (IGNORED.has(prop)) continue;\n switch (prop) {\n case \"display\":\n if (value === \"flex\" || value === \"inline-flex\") set(\"display\", \"flex\");\n else if (value === \"grid\") {\n // Our only grids are equal-track column layouts; flex row reproduces\n // them exactly and is honoured by the engine. Whether the row wraps\n // depends on the child count, which the translator decides.\n set(\"display\", \"flex\");\n set(\"flexDirection\", \"row\");\n } else if (value === \"none\") set(\"display\", \"none\");\n break;\n case \"flex-direction\":\n set(\"flexDirection\", FLEX_DIRECTION[value]);\n break;\n case \"justify-content\":\n set(\"justifyContent\", JUSTIFY[value]);\n break;\n case \"align-items\":\n set(\"alignItems\", ALIGN[value]);\n break;\n case \"align-self\":\n set(\"alignSelf\", ALIGN[value]);\n break;\n case \"flex-wrap\":\n set(\"flexWrap\", value === \"wrap\" ? \"wrap\" : \"nowrap\");\n break;\n case \"flex\":\n set(\"flexGrow\", num(value.split(/\\s+/)[0] ?? \"0\"));\n break;\n case \"flex-grow\":\n set(\"flexGrow\", num(value));\n break;\n case \"flex-shrink\":\n set(\"flexShrink\", num(value));\n break;\n case \"gap\":\n case \"row-gap\":\n case \"column-gap\": {\n const parts = value.split(/\\s+/).map((p) => length(p));\n const first = typeof parts[0] === \"number\" ? parts[0] : undefined;\n const second = parts.length > 1 && typeof parts[1] === \"number\" ? parts[1] : first;\n if (prop === \"gap\") {\n set(\"rowGap\", first);\n set(\"columnGap\", second);\n } else set(prop === \"row-gap\" ? \"rowGap\" : \"columnGap\", first);\n break;\n }\n case \"grid-template-columns\":\n // Track count is recovered by the translator, which turns our 12-track\n // rows into proportional flex children.\n break;\n case \"grid-column\": {\n // \"span 6\" of 12 tracks: grow in proportion to the span.\n const span = /^span\\s+(\\d+)$/.exec(value);\n if (span) {\n set(\"flexGrow\", Number(span[1]));\n set(\"flexBasis\", 0);\n }\n break;\n }\n case \"width\":\n set(\"width\", length(value));\n break;\n case \"height\": {\n // A percentage height is a CSS-ism for \"fill the row\"; in a flow layout\n // it has no meaningful referent, and the engine resolves it to points,\n // which would inflate every row it appears on. Flex stretch covers it.\n const h = length(value);\n if (typeof h === \"number\") set(\"height\", h);\n break;\n }\n case \"padding\":\n set(\"padding\", edges(value));\n break;\n case \"padding-top\":\n case \"padding-right\":\n case \"padding-bottom\":\n case \"padding-left\":\n set(`padding${cap(prop.slice(8))}`, length(value));\n break;\n case \"margin\":\n set(\"margin\", edges(value));\n break;\n case \"margin-top\":\n case \"margin-right\":\n case \"margin-bottom\":\n case \"margin-left\":\n set(`margin${cap(prop.slice(7))}`, length(value));\n break;\n case \"background\":\n case \"background-color\":\n set(\"backgroundColor\", colour(value));\n break;\n case \"color\":\n set(\"color\", colour(value));\n break;\n case \"font-family\":\n set(\"fontFamily\", value.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\"));\n break;\n case \"font-size\":\n set(\"fontSize\", length(value));\n break;\n case \"font-weight\":\n set(\"fontWeight\", value === \"bold\" ? 700 : value === \"normal\" ? 400 : num(value));\n break;\n case \"font-style\":\n if (value === \"italic\") set(\"fontStyle\", \"italic\");\n break;\n case \"line-height\":\n set(\"lineHeight\", num(value));\n break;\n case \"letter-spacing\":\n if (value.endsWith(\"px\")) set(\"letterSpacing\", length(value));\n break;\n case \"text-align\":\n set(\"textAlign\", TEXT_ALIGN[value]);\n break;\n case \"text-transform\":\n if (value !== \"none\") set(\"textTransform\", value);\n break;\n case \"text-decoration\":\n if (value.includes(\"underline\")) set(\"textDecoration\", \"underline\");\n else if (value.includes(\"line-through\")) set(\"textDecoration\", \"line-through\");\n break;\n case \"opacity\":\n set(\"opacity\", num(value));\n break;\n case \"overflow\":\n if (value === \"hidden\") set(\"overflow\", \"hidden\");\n break;\n case \"border-radius\": {\n const r = length(value.split(/\\s+/)[0] ?? \"0\");\n set(\"borderRadius\", typeof r === \"number\" ? r : undefined);\n break;\n }\n case \"border\": {\n const b = border(value);\n if (b) {\n set(\"borderWidth\", b.width);\n set(\"borderColor\", b.colour);\n }\n break;\n }\n case \"border-top\":\n case \"border-right\":\n case \"border-bottom\":\n case \"border-left\": {\n const side = cap(prop.slice(7));\n const b = border(value);\n if (b) {\n set(`border${side}Width`, b.width);\n set(`border${side}Color`, b.colour);\n }\n break;\n }\n case \"position\":\n // Relative matters as much as absolute: it is what makes a box the\n // frame its absolutely positioned children are measured from.\n if (value === \"absolute\" || value === \"relative\") set(\"position\", value);\n break;\n case \"top\":\n case \"left\":\n case \"right\":\n case \"bottom\":\n set(prop, length(value));\n break;\n default:\n unsupported.push(prop);\n }\n }\n // CSS defaults `flex-direction` to row; the engine's React-Native-flavoured\n // model defaults to column. Without this every unqualified `display: flex`\n // silently stacks — the single largest source of layout drift we found.\n if (s.display === \"flex\" && s.flexDirection === undefined) s.flexDirection = \"row\";\n return { style: s, unsupported };\n}\n\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","/**\n * VNode → Forme document node.\n *\n * Block renderers (built-in and custom alike) return a VNode tree, so a single\n * translator gives every block a browserless PDF path for free — no block has\n * to know Forme exists.\n *\n * Alongside each emitted node the translator records an `Annotation` in exactly\n * the same shape. That is what lets `measure.ts` map Forme's layout result back\n * onto BroadPaper node keys without the engine needing to carry our identifiers.\n */\nimport { classNames, styleString, toHtml, walkVNodes, type VNode } from \"@broadpaper/core\";\nimport { mapStyle, mapColumnWidth } from \"@formepdf/shared\";\nimport { parseDeclarations, translateStyle, length, pxToPt, type FormeStyle } from \"./style.js\";\nimport { splitSvg, svgFromDataUri, type SvgLabel } from \"./svg.js\";\nimport type { Annotation } from \"./measure.js\";\n\nexport interface FormeNode {\n kind: Record<string, unknown>;\n style: FormeStyle;\n children: FormeNode[];\n href?: string;\n alt?: string;\n}\n\nexport interface TranslateContext {\n warnings: Set<string>;\n /**\n * Keeps design-mode affordances — placeholders, empty-slot outlines, the\n * page-break rule. They never belong in a PDF, but when this translation is\n * measuring the editor's canvas they are part of what the canvas draws, and\n * measuring them as nothing makes blocks invisible on screen.\n */\n design?: boolean;\n /**\n * Drops page-break nodes, for the passes where BroadPaper has already decided\n * the pages. Measurement uses one unbounded page and reads back only its\n * first, so a break there would silently discard everything after it; the\n * paginated draw pass has placed its content already and must not reflow.\n */\n suppressPageBreaks?: boolean;\n}\n\n/** An emitted node paired with its annotation. */\nexport interface Translated {\n node: FormeNode;\n ann: Annotation;\n}\n\nconst INLINE_TAGS = new Set([\"span\", \"strong\", \"b\", \"em\", \"i\", \"u\", \"s\", \"code\", \"a\", \"small\"]);\nconst TEXT_BLOCK_TAGS = new Set([\"p\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"li\", \"blockquote\", \"figcaption\", \"label\", \"td\", \"th\", \"div\"]);\n\nfunction declarationsOf(v: VNode): Record<string, string> {\n return parseDeclarations(typeof v.props.style === \"string\" ? v.props.style : styleString(v.props.style));\n}\n\nfunction styleOf(v: VNode, ctx: TranslateContext): FormeStyle {\n const decls = declarationsOf(v);\n const { style, unsupported } = translateStyle(decls);\n for (const u of unsupported) ctx.warnings.add(`unsupported CSS property \"${u}\" (ignored)`);\n // Forme's own public mapper produces the engine JSON, so enum spellings and\n // dimension wrappers stay correct as the engine evolves.\n return mapStyle(style as never) as FormeStyle;\n}\n\n/** Flattens an element's descendants into a single string of text. */\nfunction textOf(v: VNode | string): string {\n if (typeof v === \"string\") return v;\n if (v.tag === \"br\") return \"\\n\";\n return v.children.map(textOf).join(\"\");\n}\n\nfunction hasBlockChild(v: VNode): boolean {\n return v.children.some((c) => typeof c !== \"string\" && !INLINE_TAGS.has(c.tag) && c.tag !== \"br\");\n}\n\n/** True when this subtree holds wrapped body text whose line boxes we want. */\nfunction holdsWrappedText(v: VNode): boolean {\n let found = false;\n walkVNodes(v, (n) => {\n if (n.props[\"data-part\"] === \"text\") found = true;\n return !found;\n });\n return found;\n}\n\nfunction leaf(node: FormeNode, ann: Annotation = { children: [] }): Translated {\n return { node, ann };\n}\n\nfunction svgNode(v: VNode, ctx: TranslateContext): Translated {\n const width = Number(v.props.width) || 0;\n const height = Number(v.props.height) || 0;\n // The engine builds its own SVG viewport from width, height and view_box, so\n // `content` is the markup that goes inside it. Handing it a whole <svg>\n // element instead nests one viewport in another: the inner one keeps our\n // pixel dimensions inside an outer one sized in points, and every chart is\n // drawn a third too large and clipped by its box.\n const { markup, labels } = splitSvg(v, (message) => ctx.warnings.add(message));\n const viewBox = typeof v.props.viewBox === \"string\" ? v.props.viewBox : `0 0 ${width} ${height}`;\n // The size goes in the style as well as the kind. Without a box the engine\n // lays the node out as auto and it takes whatever room is going, which turns\n // a 19px trend arrow into a line of its own.\n const box = mapStyle({ width: pxToPt(width), height: pxToPt(height) } as never) as FormeStyle;\n const shapes: FormeNode = {\n kind: { type: \"Svg\", width: pxToPt(width), height: pxToPt(height), view_box: viewBox, content: markup },\n style: { ...box, ...styleOf(v, ctx) },\n children: []\n };\n if (!labels.length) return leaf(shapes);\n\n // The engine does not draw SVG text, so the labels are placed over the chart\n // as real text. Positions come from the view box, which is the coordinate\n // system the labels were written in.\n const vb = viewBox.trim().split(/[\\s,]+/).map(Number);\n const sx = vb.length === 4 && vb[2] ? width / vb[2]! : 1;\n const sy = vb.length === 4 && vb[3] ? height / vb[3]! : 1;\n const children = [shapes, ...labels.map((l) => labelNode(l, sx, sy))];\n return {\n node: {\n kind: { type: \"View\" },\n // Relative, so the labels are placed against this box rather than the page.\n style: mapStyle({ position: \"relative\", width: pxToPt(width), height: pxToPt(height) } as never) as FormeStyle,\n children\n },\n ann: { children: children.map(() => ({ children: [] })) }\n };\n}\n\n/** One SVG label, positioned over the chart it was lifted out of. */\nfunction labelNode(l: SvgLabel, sx: number, sy: number): FormeNode {\n const x = l.x * sx;\n const size = l.fontSize * Math.min(sx, sy);\n // SVG anchors text at a point; the engine positions a box. Without knowing\n // the shaped width we estimate it — 0.55em is close for the sans faces\n // reports use — and place the box so the anchor point lands where the SVG\n // asked. A box wide enough to never wrap but no wider keeps a label from\n // being pushed around inside a small graphic such as a logo.\n const estimate = Math.max(size, l.text.length * size * 0.55);\n const width = estimate * 1.5;\n const left = l.anchor === \"middle\" ? x - estimate / 2 : l.anchor === \"end\" ? x - estimate : x;\n const style: Record<string, unknown> = {\n position: \"absolute\",\n left: pxToPt(left),\n // `y` is a baseline; a box starts roughly one ascender higher.\n top: pxToPt(l.y * sy - size * 0.8),\n width: pxToPt(width),\n fontSize: pxToPt(size),\n textAlign: \"left\"\n };\n if (l.fill) style.color = l.fill;\n if (l.fontFamily) style.fontFamily = l.fontFamily.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\");\n if (l.fontWeight) style.fontWeight = l.fontWeight;\n return { kind: { type: \"Text\", content: l.text }, style: mapStyle(style as never) as FormeStyle, children: [] };\n}\n\n/**\n * The size an inline SVG should be drawn at.\n *\n * An `<img>` is usually sized by CSS rather than by the artwork, so a logo\n * styled to 28px tall must be drawn at 28px tall and not at its intrinsic 48.\n * The aspect ratio comes from the artwork whenever only one dimension is given.\n */\nfunction sizeFrom(img: VNode, svg: VNode): { width: number; height: number } {\n const own = { width: Number(svg.props.width) || 0, height: Number(svg.props.height) || 0 };\n const box = String(svg.props.viewBox ?? \"\").trim().split(/[\\s,]+/).map(Number);\n const natural = {\n width: own.width || (box.length === 4 ? box[2]! : 0),\n height: own.height || (box.length === 4 ? box[3]! : 0)\n };\n const css = parseDeclarations(typeof img.props.style === \"string\" ? img.props.style : styleString(img.props.style));\n const asked = { width: Number.parseFloat(css.width ?? \"\"), height: Number.parseFloat(css.height ?? \"\") };\n const ratio = natural.width && natural.height ? natural.width / natural.height : 0;\n\n let width = Number.isFinite(asked.width) ? asked.width : 0;\n let height = Number.isFinite(asked.height) ? asked.height : 0;\n if (!width && height && ratio) width = height * ratio;\n if (!height && width && ratio) height = width / ratio;\n return { width: width || natural.width, height: height || natural.height };\n}\n\nfunction tableNode(v: VNode, ctx: TranslateContext): Translated {\n const columns: Array<{ width: unknown }> = [];\n const rows: FormeNode[] = [];\n const rowAnns: Annotation[] = [];\n const rowKinds: Array<\"header\" | \"body\" | \"footer\"> = [];\n\n const visit = (node: VNode, kind: \"header\" | \"body\" | \"footer\") => {\n for (const child of node.children) {\n if (typeof child === \"string\") continue;\n if (child.tag === \"colgroup\") {\n for (const col of child.children) {\n if (typeof col === \"string\") continue;\n const w = parseDeclarations(typeof col.props.style === \"string\" ? col.props.style : styleString(col.props.style)).width;\n const parsed = w ? length(w) : undefined;\n // Forme sizes table columns by fraction or fixed points; our percentage\n // widths become fractions of the table width.\n columns.push({\n width: mapColumnWidth(\n typeof parsed === \"string\" ? { fraction: Number.parseFloat(parsed) / 100 } : typeof parsed === \"number\" ? { fixed: parsed } : \"auto\"\n )\n });\n }\n } else if (child.tag === \"thead\") visit(child, \"header\");\n else if (child.tag === \"tbody\") visit(child, \"body\");\n else if (child.tag === \"tfoot\") visit(child, \"footer\");\n else if (child.tag === \"tr\") {\n const cells: FormeNode[] = [];\n const cellAnns: Annotation[] = [];\n for (const cell of child.children) {\n if (typeof cell === \"string\") continue;\n const inner = childNodes(cell, ctx);\n cells.push({\n kind: { type: \"TableCell\", col_span: Number(cell.props.colspan) || 1, row_span: Number(cell.props.rowspan) || 1 },\n style: styleOf(cell, ctx),\n children: inner.nodes\n });\n cellAnns.push({ children: inner.anns });\n }\n rows.push({ kind: { type: \"TableRow\", is_header: kind === \"header\" }, style: styleOf(child, ctx), children: cells });\n rowAnns.push({ children: cellAnns });\n rowKinds.push(kind);\n }\n }\n };\n visit(v, \"body\");\n return {\n node: { kind: { type: \"Table\", columns }, style: styleOf(v, ctx), children: rows },\n ann: { rowKinds, children: rowAnns }\n };\n}\n\n/** Style props that describe glyphs rather than the box around them. */\nconst TEXT_PROPS = [\"color\", \"fontFamily\", \"fontSize\", \"fontWeight\", \"fontStyle\", \"lineHeight\", \"letterSpacing\", \"textAlign\", \"textTransform\", \"textDecoration\"] as const;\n\nfunction textStyleOf(style: FormeStyle): FormeStyle {\n const out: FormeStyle = {};\n for (const k of TEXT_PROPS) if (style[k] !== undefined) out[k] = style[k];\n return out;\n}\n\nfunction childNodes(v: VNode, ctx: TranslateContext, inherited: FormeStyle = {}): { nodes: FormeNode[]; anns: Annotation[] } {\n const nodes: FormeNode[] = [];\n const anns: Annotation[] = [];\n for (const child of v.children) {\n if (typeof child === \"string\") {\n if (!child.trim()) continue;\n // The engine's model is React-Native-flavoured: a view's font and colour\n // do not reach a text node inside it, so they are copied down.\n nodes.push({ kind: { type: \"Text\", content: child }, style: inherited, children: [] });\n anns.push({ children: [] });\n continue;\n }\n const t = translate(child, ctx);\n if (!t) continue;\n nodes.push(t.node);\n anns.push(t.ann);\n }\n return { nodes, anns };\n}\n\n/** Translates one VNode, returning the emitted node and its annotation. */\nexport function translate(v: VNode, ctx: TranslateContext): Translated | null {\n const cls = classNames(v.props.class);\n // Design-mode affordances never belong in a PDF, but they do belong in a\n // measurement of the design canvas, which draws them.\n if (!ctx.design && /bp-(placeholder|empty-section|empty-column)\\b/.test(cls)) return null;\n if (/bp-page-break\\b/.test(cls) && !ctx.suppressPageBreaks) return leaf({ kind: { type: \"PageBreak\" }, style: {}, children: [] });\n\n let result: Translated | null;\n switch (v.tag) {\n case \"svg\":\n result = svgNode(v, ctx);\n break;\n case \"table\":\n result = tableNode(v, ctx);\n break;\n case \"img\": {\n const src = typeof v.props.src === \"string\" ? v.props.src : \"\";\n if (!src) return null;\n // An SVG data URI is vector artwork, not a bitmap. The engine's image\n // decoder cannot read one and leaves a grey box where the logo should be,\n // so treat it as the drawing it is.\n const vector = svgFromDataUri(src);\n if (vector) {\n const sized: VNode = { ...vector, props: { ...vector.props, ...sizeFrom(v, vector) } };\n result = svgNode(sized, ctx);\n break;\n }\n const node: FormeNode = { kind: { type: \"Image\", src }, style: styleOf(v, ctx), children: [] };\n if (typeof v.props.alt === \"string\" && v.props.alt) node.alt = v.props.alt;\n result = leaf(node);\n break;\n }\n case \"br\":\n result = leaf({ kind: { type: \"Text\", content: \"\\n\" }, style: {}, children: [] });\n break;\n case \"ul\":\n case \"ol\": {\n const items: FormeNode[] = [];\n const itemAnns: Annotation[] = [];\n for (const li of v.children) {\n if (typeof li === \"string\") continue;\n const inner = childNodes(li, ctx);\n items.push({ kind: { type: \"ListItem\" }, style: styleOf(li, ctx), children: inner.nodes });\n itemAnns.push({ children: inner.anns });\n }\n result = {\n // Marker names are the CSS `list-style-type` spellings, not capitalised\n // variant names: the engine rejects the whole document over one wrong\n // enum, so a single bullet list used to mean no PDF at all.\n node: { kind: { type: \"List\", ordered: v.tag === \"ol\", marker_type: v.tag === \"ol\" ? \"decimal\" : \"disc\", start: 1 }, style: styleOf(v, ctx), children: items },\n ann: { children: itemAnns }\n };\n break;\n }\n case \"colgroup\":\n case \"col\":\n return null;\n default:\n result = null;\n }\n\n if (!result) {\n const style = styleOf(v, ctx);\n const heading = /^h([1-6])$/.exec(v.tag);\n\n const content = textOf(v);\n const blank = !content.trim();\n if (blank && !Object.keys(style).length && !v.children.length) return null;\n\n // A text block with only inline content becomes one Text node; the inline\n // runs are flattened into it so their content survives.\n //\n // A text node with nothing in it is a different matter. Spacers and\n // dividers are empty `div`s carrying only a height or a border, and the\n // engine gives every Text node a line box — so translating them as text\n // would silently add a line's worth of height that no browser shows. They\n // become plain views instead. An intentionally empty paragraph keeps its\n // blank line, because there the line is the point.\n // An element that lays its children out — flex or grid — is a layout box\n // even when every child is an inline tag, or a bare string. Flattening one\n // into a run of text turns \"Lower risk … Higher risk\" into\n // \"Lower riskHigher risk\", and turns a callout's round badge into a text\n // node that paints neither its background nor its border.\n const decls = declarationsOf(v);\n const laysOut = decls.display === \"flex\" || decls.display === \"inline-flex\" || decls.display === \"grid\";\n const textual = (TEXT_BLOCK_TAGS.has(v.tag) || INLINE_TAGS.has(v.tag) || heading) && !hasBlockChild(v) && !laysOut;\n if (textual && (!blank || /bp-p--empty/.test(cls))) {\n const kind: Record<string, unknown> = heading ? { type: \"Heading\", level: Number(heading[1]), content } : { type: \"Text\", content };\n const node: FormeNode = { kind, style, children: [] };\n if (v.tag === \"a\" && typeof v.props.href === \"string\") node.href = v.props.href;\n result = leaf(node);\n } else {\n const inner = childNodes(v, ctx);\n // An empty view still draws when it carries a rule, a fill or a height —\n // that is exactly what our spacers and dividers are.\n const draws = Object.keys(style).some((k) => /^border[A-Za-z]*Width$/.test(k)) || style.backgroundColor !== undefined || style.height !== undefined;\n if (inner.nodes.length === 0 && !draws) return null;\n if (decls.display === \"grid\") applyGridAsFlex(style, inner.nodes, decls);\n const node: FormeNode = { kind: { type: \"View\" }, style, children: inner.nodes };\n if (v.tag === \"a\" && typeof v.props.href === \"string\") node.href = v.props.href;\n result = { node, ann: { children: inner.anns } };\n }\n }\n\n // Block wrappers carry `data-key`; that is our handle for mapping geometry back.\n const key = v.props[\"data-key\"];\n if (typeof key === \"string\") {\n result.ann.key = key;\n if (holdsWrappedText(v)) result.ann.text = true;\n // A table sits inside its block's wrapper, so lift the row roles onto the\n // keyed node — that is where the paginator looks for them.\n if (!result.ann.rowKinds) {\n const rows = findRowKinds(result.ann);\n if (rows) result.ann.rowKinds = rows;\n }\n }\n return result;\n}\n\n/**\n * Reproduces one of our CSS grids with flexbox.\n *\n * Rows declare twelve tracks and their columns a span, which becomes a\n * proportional `flexGrow`. A grid whose children outnumber its tracks (the\n * key/value grid) genuinely wraps, so it keeps `flexWrap` and a per-track\n * basis; a row that fits on one line must not wrap, or an over-wide child such\n * as a logo pushes the next column onto a second line.\n */\nfunction applyGridAsFlex(style: FormeStyle, children: FormeNode[], decls: Record<string, string>): void {\n const tracks = /repeat\\(\\s*(\\d+)/.exec(decls[\"grid-template-columns\"] ?? \"\");\n const spanned = children.filter((c) => typeof c.style.flexGrow === \"number\" && c.style.flexGrow > 0).length;\n const perRow = tracks && spanned === 0 ? Number(tracks[1]) : children.length;\n const wraps = children.length > perRow;\n style.flexWrap = wraps ? \"Wrap\" : \"NoWrap\";\n for (const child of children) {\n if (child.style.flexGrow === undefined) {\n child.style.flexGrow = 1;\n child.style.flexBasis = wraps ? { Percent: 100 / Math.max(1, perRow) } : { Pt: 0 };\n }\n // Columns must give way rather than overflow: a wide logo or a long word\n // should shrink its column, never push a sibling onto the next line.\n if (child.style.flexShrink === undefined) child.style.flexShrink = 1;\n if (child.style.minWidth === undefined) child.style.minWidth = { Pt: 0 };\n }\n}\n\n/** First `rowKinds` found in a subtree, so a wrapper can adopt its table's rows. */\nfunction findRowKinds(ann: Annotation): Annotation[\"rowKinds\"] | undefined {\n if (ann.rowKinds) return ann.rowKinds;\n for (const c of ann.children) {\n const found = findRowKinds(c);\n if (found) return found;\n }\n return undefined;\n}\n\n/** Translates one VNode. Returns null for nodes that draw nothing. */\nexport function vnodeToForme(v: VNode, ctx: TranslateContext): FormeNode | null {\n return translate(v, ctx)?.node ?? null;\n}\n","/**\n * Bakes `translate(...)` transforms into the coordinates they move.\n *\n * The engine's SVG renderer does not apply transforms on groups. Our charts\n * lean on them heavily — a donut is arcs drawn around the origin and moved to\n * the centre, a legend is rows moved down one line at a time — so without this\n * every one of those pieces lands on top of the origin and the chart is\n * unreadable.\n *\n * Flattening at this boundary rather than in the chart code keeps the charts\n * written the way SVG is normally written, and covers custom blocks that emit\n * SVG of their own. Only translation is flattened; anything else is left in\n * place and reported, because silently drawing it wrong is worse than saying so.\n */\nimport { toHtml, type VNode, type VProps } from \"@broadpaper/core\";\n\n/** Attributes that carry a coordinate, and which axis each one moves along. */\nconst COORDS: Record<string, Array<[attr: string, axis: 0 | 1]>> = {\n rect: [[\"x\", 0], [\"y\", 1]],\n circle: [[\"cx\", 0], [\"cy\", 1]],\n ellipse: [[\"cx\", 0], [\"cy\", 1]],\n line: [[\"x1\", 0], [\"y1\", 1], [\"x2\", 0], [\"y2\", 1]],\n text: [[\"x\", 0], [\"y\", 1]],\n tspan: [[\"x\", 0], [\"y\", 1]],\n image: [[\"x\", 0], [\"y\", 1]],\n use: [[\"x\", 0], [\"y\", 1]]\n};\n\nconst TRANSLATE = /^\\s*translate\\(\\s*(-?[\\d.eE+]+)\\s*(?:[, ]\\s*(-?[\\d.eE+]+))?\\s*\\)\\s*$/;\n\n/** Parses `translate(x, y)`. Returns null for anything else, including no transform. */\nfunction translationOf(value: unknown): [number, number] | null | \"unsupported\" {\n if (typeof value !== \"string\" || !value.trim()) return null;\n const m = TRANSLATE.exec(value);\n if (!m) return \"unsupported\";\n return [Number(m[1]), m[2] === undefined ? 0 : Number(m[2])];\n}\n\n/** Number of parameters each path command takes, and which of them are coordinates. */\nconst PATH_COMMANDS: Record<string, { size: number; coords: number[] }> = {\n m: { size: 2, coords: [0, 1] },\n l: { size: 2, coords: [0, 1] },\n t: { size: 2, coords: [0, 1] },\n h: { size: 1, coords: [0] },\n v: { size: 1, coords: [1] },\n c: { size: 6, coords: [0, 1, 0, 1, 0, 1] },\n s: { size: 4, coords: [0, 1, 0, 1] },\n q: { size: 4, coords: [0, 1, 0, 1] },\n // rx ry rotation large-arc sweep x y — only the final pair is a position.\n a: { size: 7, coords: [-1, -1, -1, -1, -1, 0, 1] },\n z: { size: 0, coords: [] }\n};\n\n/**\n * Shifts a path's absolute coordinates. Relative commands describe deltas and\n * are already correct, except for a leading `m`, which the spec treats as\n * absolute because there is no current point to be relative to.\n */\nexport function translatePathData(d: string, dx: number, dy: number): string {\n if (!dx && !dy) return d;\n const tokens = d.match(/[a-zA-Z]|-?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return d;\n\n const out: string[] = [];\n let command = \"\";\n let i = 0;\n let first = true;\n\n while (i < tokens.length) {\n const token = tokens[i]!;\n if (/[a-zA-Z]/.test(token)) {\n command = token;\n out.push(token);\n i++;\n if (command.toLowerCase() === \"z\") {\n first = false;\n continue;\n }\n }\n const spec = PATH_COMMANDS[command.toLowerCase()];\n if (!spec || spec.size === 0) {\n // A command we do not know: copy the rest through untouched rather than\n // guess at its parameters and corrupt the path.\n while (i < tokens.length) out.push(tokens[i++]!);\n break;\n }\n // An implicit repeat of `M`/`m` continues as `L`/`l`.\n const absolute = command === command.toUpperCase() || (first && command === \"m\");\n for (let p = 0; p < spec.size && i < tokens.length; p++) {\n const axis = spec.coords[p]!;\n const value = Number(tokens[i]!);\n out.push(absolute && axis >= 0 ? String(round(value + (axis === 0 ? dx : dy))) : tokens[i]!);\n i++;\n }\n if (first) {\n first = false;\n if (command === \"m\") command = \"l\";\n else if (command === \"M\") command = \"L\";\n }\n }\n return out.join(\" \");\n}\n\nfunction round(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n\n/** Shifts a `points` list, as used by polyline and polygon. */\nfunction translatePoints(points: string, dx: number, dy: number): string {\n const nums = points.match(/-?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!nums) return points;\n return nums.map((n, i) => round(Number(n) + (i % 2 === 0 ? dx : dy))).join(\" \");\n}\n\nfunction shift(v: VNode, dx: number, dy: number, warn: (message: string) => void): VNode {\n const own = translationOf(v.props.transform);\n let tx = dx;\n let ty = dy;\n const props: VProps = { ...v.props };\n\n if (own === \"unsupported\") {\n warn(`SVG transform \"${String(v.props.transform)}\" is not translate() and was left to the engine, which ignores it`);\n } else if (own) {\n tx += own[0];\n ty += own[1];\n delete props.transform;\n }\n\n if (tx || ty) {\n for (const [attr, axis] of COORDS[v.tag] ?? []) {\n // An absent coordinate defaults to zero, and zero still has to move.\n const current = props[attr] as unknown;\n const base = current === undefined || current === null || current === \"\" ? 0 : Number(current);\n if (Number.isFinite(base)) props[attr] = round(base + (axis === 0 ? tx : ty));\n }\n if (v.tag === \"path\" && typeof props.d === \"string\") props.d = translatePathData(props.d, tx, ty);\n if ((v.tag === \"polyline\" || v.tag === \"polygon\") && typeof props.points === \"string\") props.points = translatePoints(props.points, tx, ty);\n }\n\n const children = v.children.map((c) => (typeof c === \"string\" ? c : shift(c, tx, ty, warn)));\n return { ...v, props, children };\n}\n\n/** A label lifted out of an SVG, in the SVG's own user units. */\nexport interface SvgLabel {\n x: number;\n y: number;\n text: string;\n anchor: \"start\" | \"middle\" | \"end\";\n fontSize: number;\n fontFamily?: string;\n fontWeight?: number;\n fill?: string;\n}\n\nfunction textContent(v: VNode | string): string {\n if (typeof v === \"string\") return v;\n return v.children.map(textContent).join(\"\");\n}\n\nfunction numeric(value: unknown, fallback: number): number {\n const n = typeof value === \"number\" ? value : Number.parseFloat(String(value ?? \"\"));\n return Number.isFinite(n) ? n : fallback;\n}\n\n/**\n * Splits an SVG into the shapes the engine can draw and the labels it cannot.\n *\n * The engine renders paths, rects and circles but not `<text>`, so axis labels,\n * legends and the number in the middle of a donut simply vanish. Lifting them\n * out and drawing them as real text is better than rasterising the chart: the\n * words stay selectable, searchable and available to a screen reader.\n *\n * Coordinates are absolute by this point, because transforms are flattened\n * first. Groups survive as `<g>` so that presentation attributes they carry —\n * fill, stroke, opacity — still inherit to their children.\n */\n/** Attributes a browser uses to make a chart interactive; meaningless in a PDF. */\nconst SCREEN_ONLY = /^data-bp-/;\n\nexport function splitSvg(v: VNode, warn: (message: string) => void): { markup: string; labels: SvgLabel[] } {\n const flat = shift(v, 0, 0, warn);\n const labels: SvgLabel[] = [];\n\n const strip = (node: VNode, inherited: { fontFamily?: string; fill?: string }): VNode | null => {\n const own = {\n fontFamily: (node.props[\"font-family\"] as string | undefined) ?? inherited.fontFamily,\n fill: (node.props.fill as string | undefined) ?? inherited.fill\n };\n if (node.tag === \"text\") {\n const text = textContent(node).trim();\n if (text) {\n const anchor = String(node.props[\"text-anchor\"] ?? \"start\");\n labels.push({\n x: numeric(node.props.x, 0),\n y: numeric(node.props.y, 0),\n text,\n anchor: anchor === \"middle\" || anchor === \"end\" ? anchor : \"start\",\n fontSize: numeric(node.props[\"font-size\"], 10),\n fontFamily: own.fontFamily,\n fontWeight: node.props[\"font-weight\"] ? numeric(node.props[\"font-weight\"], 400) : undefined,\n fill: own.fill\n });\n }\n return null;\n }\n const children: Array<VNode | string> = [];\n for (const c of node.children) {\n if (typeof c === \"string\") {\n children.push(c);\n continue;\n }\n const kept = strip(c, own);\n if (kept) children.push(kept);\n }\n // Screen-only attributes are dropped here, so the markup handed to the\n // engine is exactly what it was before charts became interactive. A PDF has\n // nothing to hover.\n const props: VNode[\"props\"] = {};\n for (const [k, value] of Object.entries(node.props)) if (!SCREEN_ONLY.test(k)) props[k] = value;\n return { ...node, props, children };\n };\n\n const kept = strip(flat, {})!;\n return { markup: kept.children.map((c) => (typeof c === \"string\" ? c : toHtml(c))).join(\"\"), labels };\n}\n\n/* ------------------------------------------------------------------ */\n/* Parsing SVG that arrives as markup rather than as a VNode */\n/* ------------------------------------------------------------------ */\n\nconst ENTITIES: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \"\\u00a0\" };\n\nfunction decodeEntities(s: string): string {\n return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (whole, body: string) => {\n if (body.startsWith(\"#x\") || body.startsWith(\"#X\")) return String.fromCodePoint(Number.parseInt(body.slice(2), 16));\n if (body.startsWith(\"#\")) return String.fromCodePoint(Number.parseInt(body.slice(1), 10));\n return ENTITIES[body] ?? whole;\n });\n}\n\nconst TAG = /<\\s*(\\/)?\\s*([a-zA-Z][\\w:.-]*)((?:\\s+[\\w:.-]+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s\">]+))*)\\s*(\\/)?\\s*>/g;\nconst ATTR = /([\\w:.-]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\">]+))/g;\nconst SKIP = /<\\?[\\s\\S]*?\\?>|<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<![\\s\\S]*?>/g;\n\n/**\n * Parses a standalone SVG document into a VNode.\n *\n * Logos and other brand assets routinely arrive as an SVG data URI in an\n * `<img>`, which the engine cannot decode — it produces a grey box. Parsing\n * them here puts them through the same treatment as a chart, so their\n * transforms are flattened and their text is drawn.\n *\n * This handles the subset of XML that SVG assets use: elements, attributes,\n * text and entities. It is not a general XML parser and does not try to be.\n */\nexport function parseSvgMarkup(source: string): VNode | null {\n const text = source.replace(SKIP, \"\");\n const root: VNode = { tag: \"#root\", props: {}, children: [] };\n const stack: VNode[] = [root];\n let cursor = 0;\n\n TAG.lastIndex = 0;\n for (let m = TAG.exec(text); m; m = TAG.exec(text)) {\n const between = text.slice(cursor, m.index);\n if (between.trim()) stack[stack.length - 1]!.children.push(decodeEntities(between));\n cursor = TAG.lastIndex;\n\n const [, closing, tag, rawAttrs, selfClosing] = m;\n if (closing) {\n // Tolerate a stray close tag rather than unwinding past the root.\n if (stack.length > 1) stack.pop();\n continue;\n }\n\n const props: VProps = {};\n ATTR.lastIndex = 0;\n for (let a = ATTR.exec(rawAttrs ?? \"\"); a; a = ATTR.exec(rawAttrs ?? \"\")) {\n props[a[1]!] = decodeEntities(a[2] ?? a[3] ?? a[4] ?? \"\");\n }\n\n const node: VNode = { tag: tag!, props, children: [] };\n stack[stack.length - 1]!.children.push(node);\n if (!selfClosing) stack.push(node);\n }\n\n const svg = root.children.find((c): c is VNode => typeof c !== \"string\" && c.tag.toLowerCase() === \"svg\");\n return svg ?? null;\n}\n\n/** Decodes a `data:image/svg+xml` URI, whether percent-encoded or base64. */\nexport function svgFromDataUri(src: string): VNode | null {\n const match = /^data:image\\/svg\\+xml(;[^,]*)?,(.*)$/is.exec(src.trim());\n if (!match) return null;\n const isBase64 = (match[1] ?? \"\").toLowerCase().includes(\"base64\");\n try {\n const body = match[2] ?? \"\";\n // This runs in a browser as well as in Node, so decode without Buffer.\n const markup = isBase64 ? new TextDecoder().decode(Uint8Array.from(atob(body), (c) => c.charCodeAt(0))) : decodeURIComponent(body);\n return parseSvgMarkup(markup);\n } catch {\n return null;\n }\n}\n","/**\n * Drawing the evaluation mark with the engine's own primitives.\n *\n * Forme has a page-native watermark node, which is the right tool twice over:\n * it repeats on every page the engine emits without the caller counting them,\n * and it draws underneath the content rather than over it, so an evaluation\n * PDF reads exactly like a licensed one apart from the mark.\n *\n * The style is not optional. An unstyled watermark node draws solid black at\n * full opacity, which does make the point but also makes the document\n * unreadable — and an evaluation copy nobody can read is not an evaluation.\n */\nimport { mapStyle } from \"@formepdf/shared\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport type { FormeNode } from \"./vnode.js\";\nimport type { FormeStyle } from \"./style.js\";\n\nexport function watermarkNode(spec: WatermarkSpec): FormeNode {\n return {\n kind: { type: \"Watermark\", text: spec.text, font_size: spec.fontSize, angle: spec.angle },\n style: mapStyle({ color: spec.color, opacity: spec.opacity } as never) as FormeStyle,\n children: []\n };\n}\n","/**\n * Forme as a pure measurer.\n *\n * Forme is page-native: given a document it paginates and draws. But given a\n * page tall enough that nothing can overflow, it becomes a measurement engine —\n * it returns the laid-out tree with a box for every node, a `TextLine` per line\n * of wrapped text and a `TableRow` per row. That is exactly the geometry our own\n * paginator consumes, so BroadPaper keeps every pagination decision (keep\n * together, keep with next, orphans and widows, repeated table headers, page\n * breaks, splitting multi-column rows) while no browser is involved anywhere.\n *\n * Correlating engine output back to BroadPaper nodes is done structurally: the\n * translator records an annotation tree in lockstep with the nodes it emits, and\n * the layout tree comes back with the same shape (leaf `Text` nodes merely gain\n * `TextLine` children, which appends rather than reorders).\n */\nimport type { GeometryMap, NodeGeometry, ResolvedNode, SectionGeometry, TableRowGeometry } from \"@broadpaper/core\";\nimport type { FormeNode } from \"./vnode.js\";\n\n/** Mirrors an emitted node, carrying what we need to map geometry back. */\nexport interface Annotation {\n /** BroadPaper node key, when this node is a block wrapper. */\n key?: string;\n /** This node's subtree holds wrapped text whose line boxes we want. */\n text?: boolean;\n /** Row roles in emission order, for table nodes. */\n rowKinds?: Array<TableRowGeometry[\"kind\"]>;\n children: Annotation[];\n}\n\n/** A layout element as returned by Forme. */\nexport interface LayoutElement {\n x: number;\n y: number;\n width: number;\n height: number;\n nodeType: string;\n textContent?: string | null;\n children?: LayoutElement[];\n}\n\nexport interface LayoutPage {\n width: number;\n height: number;\n elements: LayoutElement[];\n}\n\n/** Height of the measurement page. Tall enough that nothing paginates. */\nexport const UNBOUNDED_PAGE_HEIGHT = 200_000;\n\nfunction descendants(el: LayoutElement, nodeType: string, out: LayoutElement[] = []): LayoutElement[] {\n for (const c of el.children ?? []) {\n if (c.nodeType === nodeType) out.push(c);\n descendants(c, nodeType, out);\n }\n return out;\n}\n\n/**\n * Walks the annotation tree and the layout tree together, recording a geometry\n * entry for every annotated node.\n */\nfunction collect(ann: Annotation, el: LayoutElement, origin: { x: number; y: number }, out: Record<string, NodeGeometry>): void {\n if (ann.key) {\n const g: NodeGeometry = {\n top: round(el.y - origin.y),\n height: round(el.height),\n // Both coordinates are relative to the section, which is what the\n // paginator hands back as a repeated header’s offset inside the page\n // content box. Leaving x absolute pushed every repeated table header one\n // page margin to the right and its last column off the page.\n left: round(el.x - origin.x),\n width: round(el.width)\n };\n if (ann.text) {\n const lines = descendants(el, \"TextLine\");\n if (lines.length) {\n // The paginator splits at the boundary *between* lines, so record the\n // midpoint of each gap; the last entry is the node's own bottom.\n const sorted = [...lines].sort((a, b) => a.y - b.y);\n const bounds: number[] = [];\n for (let i = 0; i < sorted.length - 1; i++) {\n const bottom = sorted[i]!.y + sorted[i]!.height;\n bounds.push(round((bottom + sorted[i + 1]!.y) / 2 - origin.y));\n }\n bounds.push(round(el.y + el.height - origin.y));\n g.lines = bounds;\n }\n }\n if (ann.rowKinds) {\n const rows = descendants(el, \"TableRow\").sort((a, b) => a.y - b.y);\n g.rows = rows.map((r, i) => ({ top: round(r.y - origin.y), height: round(r.height), kind: ann.rowKinds![i] ?? \"body\" }));\n }\n out[ann.key] = g;\n }\n const kids = el.children ?? [];\n for (let i = 0; i < ann.children.length; i++) {\n const childEl = kids[i];\n if (!childEl) continue;\n collect(ann.children[i]!, childEl, origin, out);\n }\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nexport interface MeasuredSection {\n section: ResolvedNode;\n node: FormeNode;\n ann: Annotation;\n}\n\n/**\n * Builds the geometry map our paginator expects from Forme's layout of an\n * unbounded page. `pageElements` are the top-level elements of that page, in the\n * same order as `sections`.\n */\nexport function geometryFromLayout(sections: MeasuredSection[], pageElements: LayoutElement[], width: number): GeometryMap {\n const out: GeometryMap = {};\n for (let i = 0; i < sections.length; i++) {\n const el = pageElements[i];\n const { section, ann } = sections[i]!;\n if (!el) {\n out[section.key] = { height: 0, width, nodes: {} };\n continue;\n }\n const nodes: Record<string, NodeGeometry> = {};\n collect(ann, el, { x: el.x, y: el.y }, nodes);\n const geom: SectionGeometry = { height: round(el.height), width, nodes };\n // The section itself is the origin, so it always starts at zero.\n nodes[section.key] = { top: 0, height: geom.height, left: 0, width: round(el.width) };\n out[section.key] = geom;\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ */\n/* Measurer */\n/* ------------------------------------------------------------------ */\n\nimport { renderNode, type BlockRegistry, type DocumentStyles, type FormatContext, type RenderMode, type RenderTreeOptions, type Theme } from \"@broadpaper/core\";\nimport { translate, type TranslateContext } from \"./vnode.js\";\nimport { pxToPt } from \"./style.js\";\n\nexport interface FormeRenderer {\n (doc: Record<string, unknown>): Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>;\n}\n\nexport interface FormeMeasurerOptions {\n registry: BlockRegistry;\n theme: Theme;\n styles: DocumentStyles;\n format: FormatContext;\n mode?: RenderMode;\n /** Page width in CSS pixels, used for the measurement page. */\n pageWidth: number;\n margins: { top: number; right: number; bottom: number; left: number };\n fonts?: unknown[];\n /** Injected so the caller picks the Forme entry point (node, browser, worker). */\n render: FormeRenderer;\n}\n\nfunction scale(el: LayoutElement, factor: number): LayoutElement {\n return {\n ...el,\n x: el.x * factor,\n y: el.y * factor,\n width: el.width * factor,\n height: el.height * factor,\n children: (el.children ?? []).map((c) => scale(c, factor))\n };\n}\n\n/**\n * Measures resolved sections with Forme, returning geometry in CSS pixels — the\n * same shape `DomMeasurer` produces, so the paginator and the editor cannot tell\n * which one measured.\n */\nexport class FormeMeasurer {\n readonly warnings = new Set<string>();\n\n constructor(private readonly opts: FormeMeasurerOptions) {}\n\n private renderOptions(): RenderTreeOptions {\n return {\n registry: this.opts.registry,\n theme: this.opts.theme,\n styles: this.opts.styles,\n mode: this.opts.mode ?? \"preview\",\n page: { number: 1, total: 1 },\n format: this.opts.format,\n width: this.contentWidth\n };\n }\n\n get contentWidth(): number {\n return Math.max(0, this.opts.pageWidth - this.opts.margins.left - this.opts.margins.right);\n }\n\n async measure(sections: ResolvedNode[], width = this.contentWidth): Promise<GeometryMap> {\n if (!sections.length) return {};\n const ctx: TranslateContext = { warnings: this.warnings, design: (this.opts.mode ?? \"preview\") === \"design\", suppressPageBreaks: true };\n const renderOpts = { ...this.renderOptions(), width };\n const measured: MeasuredSection[] = [];\n for (const section of sections) {\n const v = renderNode(section, renderOpts, width);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) measured.push({ section, node: t.node, ann: t.ann });\n }\n if (!measured.length) return {};\n\n const m = this.opts.margins;\n const doc: Record<string, unknown> = {\n children: [\n {\n kind: {\n type: \"Page\",\n config: {\n // Tall enough that nothing can paginate: this is a measuring page.\n size: { Custom: { width: pxToPt(this.opts.pageWidth), height: UNBOUNDED_PAGE_HEIGHT } },\n margin: { top: pxToPt(m.top), right: pxToPt(m.right), bottom: pxToPt(m.bottom), left: pxToPt(m.left) },\n wrap: true\n }\n },\n style: {},\n children: measured.map((x) => x.node)\n }\n ],\n metadata: {},\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: {}\n };\n if (this.opts.fonts?.length) doc.fonts = this.opts.fonts;\n\n const result = await this.opts.render(doc);\n const pages = ((result.layout as { pages?: LayoutPage[] } | null)?.pages ?? []) as LayoutPage[];\n // Points back to CSS pixels; BroadPaper works in pixels throughout.\n const toPx = 96 / 72;\n const elements = (pages[0]?.elements ?? []).map((e) => scale(e, toPx));\n for (const w of result.warnings ?? []) this.warnings.add(w);\n return geometryFromLayout(measured, elements, width);\n }\n}\n","/**\n * Forme as the editor's measurer.\n *\n * The canvas normally measures in the browser, which is immediate and free.\n * That is the right default, but it means the editor and the PDF are laid out\n * by two different engines, and where they disagree a page breaks in one place\n * on screen and another in the file. Measuring the canvas with the same engine\n * that renders the PDF removes the disagreement entirely: a break you see is a\n * break you get.\n *\n * The engine is injected rather than imported so this module stays neutral\n * about which Forme entry point the host uses — browser, worker or node.\n */\nimport type { GeometryMap, RenderTreeOptions, ResolvedNode, SectionGeometry } from \"@broadpaper/core\";\nimport { FormeMeasurer, type FormeRenderer } from \"./measure.js\";\n\nexport interface FormeEditorMeasurerOptions {\n /** The engine call, e.g. `renderSerializedDocWithLayout` from `@formepdf/core/browser`. */\n render: FormeRenderer;\n /** Font files the engine should use, matching the theme's families. */\n fonts?: unknown[];\n /** Called for every distinct translation warning, once. */\n onWarning?(message: string): void;\n}\n\n/** FNV-1a 32-bit. Fast, and collisions here only cost a re-measure. */\nfunction hash(s: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(36) + s.length.toString(36);\n}\n\n/**\n * Measures resolved sections with Forme, caching by section content.\n *\n * Engine measurement is far slower than reading the DOM, so an edit must not\n * re-measure the whole document. Only sections whose content actually changed\n * are sent, and they go in one call rather than one call each.\n */\nexport class FormeEditorMeasurer {\n private opts: RenderTreeOptions | null = null;\n private readonly cache = new Map<string, SectionGeometry>();\n private readonly seen = new Set<string>();\n\n constructor(private readonly config: FormeEditorMeasurerOptions) {}\n\n setOptions(opts: RenderTreeOptions): void {\n this.opts = opts;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n\n destroy(): void {\n this.cache.clear();\n }\n\n private key(section: ResolvedNode, width: number, mode: string): string {\n return hash(JSON.stringify(section)) + \":\" + Math.round(width * 100) + \":\" + mode;\n }\n\n async measure(sections: ResolvedNode[], width: number): Promise<GeometryMap> {\n const opts = this.opts;\n if (!opts) throw new Error(\"FormeEditorMeasurer.setOptions() must be called before measure()\");\n\n const out: GeometryMap = {};\n const pending: ResolvedNode[] = [];\n const keys = new Map<string, string>();\n for (const section of sections) {\n const k = this.key(section, width, opts.mode);\n const hit = this.cache.get(k);\n if (hit) out[section.key] = hit;\n else {\n pending.push(section);\n keys.set(section.key, k);\n }\n }\n if (!pending.length) return out;\n\n // The measuring page is exactly the content box: giving it the width the\n // caller asked for, with no margins, keeps the two definitions of \"width\"\n // from ever drifting apart.\n const measurer = new FormeMeasurer({\n registry: opts.registry,\n theme: opts.theme,\n styles: opts.styles,\n format: opts.format,\n mode: opts.mode,\n pageWidth: width,\n margins: { top: 0, right: 0, bottom: 0, left: 0 },\n fonts: this.config.fonts,\n render: this.config.render\n });\n\n const measured = await measurer.measure(pending, width);\n for (const [sectionKey, geometry] of Object.entries(measured)) {\n out[sectionKey] = geometry;\n const k = keys.get(sectionKey);\n if (k) this.cache.set(k, geometry);\n }\n\n for (const w of measurer.warnings) {\n if (this.seen.has(w)) continue;\n this.seen.add(w);\n this.config.onWarning?.(w);\n }\n return out;\n }\n}\n","/**\n * @broadpaper/forme — browserless PDF output.\n *\n * The Chromium backend (`@broadpaper/pdf`) prints a document BroadPaper has\n * already paginated. This backend instead hands Forme the flowing content and\n * lets its page-native Rust/WASM engine paginate and draw: no browser, no\n * native dependencies, runs in Node, edge runtimes and the browser.\n *\n * The trade-off is explicit: pagination decisions move from BroadPaper's\n * paginator to Forme's, so the editor's on-screen page breaks are an\n * approximation of this output until the editor is switched to the same engine.\n * `renderPdf` returns Forme's own page geometry so callers can compare.\n */\nimport {\n computePageGeometry,\n mergeTheme,\n renderNode,\n resolveTemplate,\n migrateTemplate,\n type BlockRegistry,\n type DataSource,\n type RenderTreeOptions,\n type ReportData,\n type ReportTemplate,\n type AnyVersionTemplate,\n type ResolvedNode,\n type Theme\n} from \"@broadpaper/core\";\nimport { mapStyle } from \"@formepdf/shared\";\nimport { producerString, resolveLicenseStatus, watermarkFor, type LicenseStatus } from \"@broadpaper/license\";\nimport { vnodeToForme, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { pxToPt } from \"./style.js\";\n\nexport { vnodeToForme, translate } from \"./vnode.js\";\nexport { FormeMeasurer, geometryFromLayout, UNBOUNDED_PAGE_HEIGHT } from \"./measure.js\";\nexport type { FormeMeasurerOptions, FormeRenderer, Annotation, LayoutElement, LayoutPage } from \"./measure.js\";\nexport type { Translated, TranslateContext } from \"./vnode.js\";\nexport type { FormeNode } from \"./vnode.js\";\nexport { translateStyle, parseDeclarations, pxToPt, PX_TO_PT } from \"./style.js\";\nexport { watermarkNode } from \"./watermark.js\";\n\n/**\n * Licensing, re-exported so a host configures BroadPaper from whichever package\n * it already imports rather than adding one for a single call.\n *\n * BroadPaper.configure({ license: process.env.BROADPAPER_LICENSE });\n *\n * Without a licence every one of these functions still renders; the PDF simply\n * carries the evaluation mark. See `@broadpaper/license`.\n */\nexport { BroadPaper, configure, resolveLicenseStatus, verifyLicense, parseLicense } from \"@broadpaper/license\";\nexport type { BroadPaperConfig, LicensePayload, LicenseState, LicenseStatus, LicenseType, Plan } from \"@broadpaper/license\";\n\nexport interface FormeFont {\n family: string;\n /** TTF/OTF bytes, a data: URI, or a filesystem path (Node only). */\n src: string | Uint8Array;\n weight?: number;\n style?: \"normal\" | \"italic\";\n}\n\nexport interface RenderFormePdfOptions {\n template: ReportTemplate | AnyVersionTemplate;\n registry: BlockRegistry;\n data?: ReportData;\n theme?: Partial<Theme>;\n dataSources?: DataSource[];\n now?: Date;\n locale?: string;\n currency?: string;\n timeZone?: string;\n metadata?: { title?: string; author?: string; subject?: string; creator?: string; lang?: string };\n /** Fonts to embed. Without these Forme falls back to its standard faces. */\n fonts?: FormeFont[];\n /** Emit a tagged (accessible) PDF. */\n tagged?: boolean;\n /** PDF/UA-1 conformance. Requires an embeddable font. */\n pdfUa?: boolean;\n /** PDF/A conformance level. */\n pdfA?: \"2b\" | \"2u\" | \"2a\" | \"3b\" | \"3u\" | \"3a\";\n /**\n * A licence for this render only, overriding whatever `configure` was given.\n *\n * Almost nothing should need it: a process renders under one licence, and\n * setting it once at startup is both less code and impossible to forget on\n * one export path. It exists for a multi-tenant host that renders on behalf\n * of several licensed organisations from one process.\n */\n license?: string | null;\n /**\n * Injected renderer, so the caller controls which Forme entry point is used\n * (`@formepdf/core`, `/browser`, or `/worker`). Defaults to a dynamic import\n * of `@formepdf/core`.\n */\n renderer?: (doc: Record<string, unknown>) => Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>;\n}\n\nexport interface FormePageInfo {\n width: number;\n height: number;\n contentWidth: number;\n contentHeight: number;\n elements: unknown[];\n}\n\nexport interface RenderFormePdfResult {\n pdf: Uint8Array;\n pages: number;\n /** Forme's own layout geometry — the basis for driving an editor from this engine. */\n layout: { pages: FormePageInfo[] } | null;\n /** Everything BroadPaper could not translate, plus everything Forme flagged. */\n warnings: string[];\n durationMs: number;\n}\n\n/**\n * Builds the Forme document JSON for a resolved BroadPaper document.\n *\n * Asynchronous only because it checks the licence, which it does itself rather\n * than taking a \"watermark this\" flag from its caller. Every route to a\n * BroadPaper PDF through this engine passes through here or through\n * `emitPages`, and a document built without the evaluation mark is a clean\n * unlicensed PDF — so the decision is made where the document is assembled and\n * nowhere else.\n */\nexport async function buildFormeDocument(opts: Omit<RenderFormePdfOptions, \"renderer\">): Promise<{ doc: Record<string, unknown>; warnings: string[]; license: LicenseStatus }> {\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const { template } = migrateTemplate(opts.template as AnyVersionTemplate);\n const theme = mergeTheme(opts.theme);\n const geom = computePageGeometry(template.page);\n const now = opts.now ?? new Date();\n const format = {\n locale: opts.locale ?? template.settings?.locale ?? \"en-GB\",\n currency: opts.currency ?? template.settings?.currency ?? \"GBP\",\n timeZone: opts.timeZone ?? template.settings?.timeZone,\n now\n };\n\n const resolved = resolveTemplate({\n template,\n registry: opts.registry,\n theme,\n dataSources: opts.dataSources,\n data: opts.data,\n mode: \"preview\",\n now,\n locale: format.locale,\n currency: format.currency,\n timeZone: format.timeZone\n });\n\n const renderOpts: RenderTreeOptions = {\n registry: opts.registry,\n theme,\n styles: template.styles,\n mode: \"preview\",\n page: { number: 1, total: 1 },\n format,\n width: geom.contentWidth\n };\n\n const ctx: TranslateContext = { warnings: new Set() };\n const translate = (sections: ResolvedNode[]): FormeNode[] => {\n const out: FormeNode[] = [];\n for (const s of sections) {\n const v = renderNode(s, renderOpts, geom.contentWidth);\n if (!v) continue;\n const node = vnodeToForme(v, ctx);\n if (node) out.push(node);\n }\n return out;\n };\n\n const children: FormeNode[] = [];\n // First child, so the mark sits under the report rather than over it. The\n // engine repeats a watermark node on every page it emits, which is what this\n // path needs: pagination here belongs to Forme, so BroadPaper does not know\n // how many pages there will be.\n const mark = watermarkFor(license);\n if (mark) children.push(watermarkNode(mark));\n // Running header/footer become Fixed regions, so page numbers and brand\n // details repeat without BroadPaper composing each page itself.\n const header = translate(resolved.header.default);\n if (header.length) children.push({ kind: { type: \"Fixed\", position: \"Header\" }, style: {}, children: header });\n const footer = translate(resolved.footer.default);\n if (footer.length) children.push({ kind: { type: \"Fixed\", position: \"Footer\" }, style: {}, children: footer });\n children.push(...translate(resolved.body));\n\n const page = {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(geom.width), height: pxToPt(geom.height) } },\n margin: { top: pxToPt(geom.margins.top), right: pxToPt(geom.margins.right), bottom: pxToPt(geom.margins.bottom), left: pxToPt(geom.margins.left) },\n wrap: true\n }\n },\n style: {},\n children\n };\n\n const doc: Record<string, unknown> = {\n children: [page],\n metadata: { title: template.name, creator: producerString(license), ...(opts.metadata ?? {}) },\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: mapStyle({ fontSize: pxToPt(theme.typography.baseFontSize ?? 11), fontFamily: theme.typography.bodyFont.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\") } as never)\n };\n if (opts.fonts?.length) doc.fonts = opts.fonts.map((f) => ({ family: f.family, src: f.src, weight: f.weight ?? 400, style: f.style ?? \"normal\" }));\n if (opts.tagged) doc.tagged = true;\n if (opts.pdfUa) doc.pdfUa = true;\n if (opts.pdfA) doc.pdfa = opts.pdfA;\n\n const warnings = [...ctx.warnings, ...resolved.warnings.map((w) => w.message)];\n return { doc, warnings, license };\n}\n\n/**\n * How this package reaches the engine when the caller injects no `renderer`.\n *\n * It is set by the entry point rather than imported here, because the two\n * runtimes need different Forme builds and a browser bundler must never even\n * see the other one. `@formepdf/core`'s default browser build is the\n * wasm-pack *bundler* target, whose `import * as wasm from \"./forme_bg.wasm\"`\n * Angular's builder rejects outright (\"WASM/ES module integration imports are\n * not supported with Zone.js applications\") — so a single bare import here\n * obliged every Angular host to go zoneless to use us at all. That is a\n * decision about the host's change detection, and a reporting SDK has no\n * business making it.\n *\n * `src/index.ts` installs the Node loader, `src/index.browser.ts` the browser\n * one, and the `browser` condition in this package's exports picks between\n * them. Neither bundle contains the other's import.\n */\nexport type EngineLoader = () => Promise<(doc: Record<string, unknown>) => Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>>;\n\nlet engineLoader: EngineLoader | null = null;\nlet engine: Awaited<ReturnType<EngineLoader>> | null = null;\n\n/**\n * Installs the engine used when no `renderer` is passed. Each entry point calls\n * this for its own runtime, which is all most hosts need; it is exported\n * because a host that reaches Forme some third way — a shared worker, a\n * pre-instantiated module, a pooled engine — has somewhere to say so once\n * rather than on every call.\n */\nexport function setEngineLoader(loader: EngineLoader): void {\n engineLoader = loader;\n}\n\nasync function defaultRenderer(doc: Record<string, unknown>) {\n if (!engineLoader) {\n throw new Error(\n \"No Forme engine is available. Import @broadpaper/forme from its package entry point, or pass a `renderer` to render with an engine you loaded yourself.\"\n );\n }\n // Cached: loading the engine means instantiating a WASM module, which is\n // expensive enough that doing it per render would dominate the render.\n engine ??= await engineLoader();\n return engine(doc);\n}\n\n/** Renders a BroadPaper template to PDF with no browser involved. */\nexport async function renderPdf(opts: RenderFormePdfOptions): Promise<RenderFormePdfResult> {\n const started = Date.now();\n const { doc, warnings } = await buildFormeDocument(opts);\n const render = opts.renderer ?? defaultRenderer;\n const result = await render(doc);\n const layout = (result.layout ?? null) as { pages: FormePageInfo[] } | null;\n return {\n pdf: result.pdf,\n pages: layout?.pages.length ?? 0,\n layout,\n warnings: [...warnings, ...(result.warnings ?? [])],\n durationMs: Date.now() - started\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* BroadPaper-paginated path */\n/* ------------------------------------------------------------------ */\n\nimport { computePageGeometry as pageGeometry, paginate, resolveValue, type GeometryMap, type PagedDocument } from \"@broadpaper/core\";\nimport { translate } from \"./vnode.js\";\nimport { geometryFromLayout, UNBOUNDED_PAGE_HEIGHT, type LayoutPage, type MeasuredSection } from \"./measure.js\";\nimport { emitPages } from \"./paged.js\";\n\nexport interface RenderPaginatedResult extends RenderFormePdfResult {\n /** The pages BroadPaper's own paginator decided. */\n paged: PagedDocument;\n /** Geometry measured by the engine, keyed by section. */\n geometry: GeometryMap;\n}\n\n/**\n * Renders with **BroadPaper owning pagination** and Forme acting only as a\n * measurer and a draw target — no browser, and every page-break rule\n * (keep together, keep with next, orphans and widows, repeated table headers,\n * explicit breaks, splitting multi-column rows) still comes from our paginator.\n *\n * Two passes through the engine: one onto a page tall enough that nothing can\n * overflow, which yields a box for every node, line and table row; then one that\n * draws the pages our paginator produced. Both passes lay text out with the same\n * engine at the same width, so the second cannot re-break what the first\n * measured.\n */\nexport async function renderPdfPaginated(opts: RenderFormePdfOptions): Promise<RenderPaginatedResult> {\n const started = Date.now();\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const { template } = migrateTemplate(opts.template as AnyVersionTemplate);\n const theme = mergeTheme(opts.theme);\n const geom = pageGeometry(template.page);\n const now = opts.now ?? new Date();\n const format = {\n locale: opts.locale ?? template.settings?.locale ?? \"en-GB\",\n currency: opts.currency ?? template.settings?.currency ?? \"GBP\",\n timeZone: opts.timeZone ?? template.settings?.timeZone,\n now\n };\n\n const resolved = resolveTemplate({\n template,\n registry: opts.registry,\n theme,\n dataSources: opts.dataSources,\n data: opts.data,\n mode: \"preview\",\n now,\n locale: format.locale,\n currency: format.currency,\n timeZone: format.timeZone\n });\n\n const renderOpts: RenderTreeOptions = {\n registry: opts.registry,\n theme,\n styles: template.styles,\n mode: \"preview\",\n page: { number: 1, total: 1 },\n format,\n width: geom.contentWidth\n };\n\n // We decided the pages; a break node here would let the engine add its own.\n const ctx: TranslateContext = { warnings: new Set(), suppressPageBreaks: true };\n const render = opts.renderer ?? defaultRenderer;\n\n /** Lays sections out on one unbounded page and reads their geometry back. */\n const measure = async (sections: ResolvedNode[]): Promise<GeometryMap> => {\n if (!sections.length) return {};\n const measured: MeasuredSection[] = [];\n for (const section of sections) {\n const v = renderNode(section, renderOpts, geom.contentWidth);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) measured.push({ section, node: t.node, ann: t.ann });\n }\n if (!measured.length) return {};\n const doc: Record<string, unknown> = {\n children: [\n {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(geom.width), height: UNBOUNDED_PAGE_HEIGHT } },\n margin: { top: pxToPt(geom.margins.top), right: pxToPt(geom.margins.right), bottom: pxToPt(geom.margins.bottom), left: pxToPt(geom.margins.left) },\n wrap: true\n }\n },\n style: {},\n children: measured.map((m) => m.node)\n }\n ],\n metadata: {},\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: baseStyle(theme)\n };\n if (opts.fonts?.length) doc.fonts = fontEntries(opts.fonts);\n const result = await render(doc);\n const pages = ((result.layout as { pages?: LayoutPage[] } | null)?.pages ?? []) as LayoutPage[];\n // Points back to CSS pixels: our paginator works in px throughout.\n const scale = 1 / PX_TO_PT_LOCAL;\n const scaled = pages[0]?.elements.map((e) => scaleElement(e, scale)) ?? [];\n return geometryFromLayout(measured, scaled, geom.contentWidth);\n };\n\n const geometry = await measure(resolved.body);\n const regionGeometry = await measure([...resolved.header.default, ...(resolved.header.firstPage ?? []), ...resolved.footer.default, ...(resolved.footer.firstPage ?? [])]);\n const paged = paginate({ document: resolved, geometry, page: geom, minPages: 1, regionGeometry });\n\n const pages = emitPages({\n resolved,\n paged,\n page: geom,\n renderOpts,\n ctx,\n geometry,\n background: template.page.background ? resolveValue(template.page.background, theme, \"#ffffff\") : undefined,\n watermark: watermarkFor(license)\n });\n const doc: Record<string, unknown> = {\n children: pages,\n metadata: { title: template.name, creator: producerString(license), ...(opts.metadata ?? {}) },\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: baseStyle(theme)\n };\n if (opts.fonts?.length) doc.fonts = fontEntries(opts.fonts);\n if (opts.tagged) doc.tagged = true;\n if (opts.pdfUa) doc.pdfUa = true;\n if (opts.pdfA) doc.pdfa = opts.pdfA;\n\n const result = await render(doc);\n const layout = (result.layout ?? null) as { pages: FormePageInfo[] } | null;\n return {\n pdf: result.pdf,\n pages: layout?.pages.length ?? paged.totalPages,\n layout,\n paged,\n geometry,\n warnings: [\n ...ctx.warnings,\n ...resolved.warnings.map((w) => w.message),\n ...paged.warnings.map((w) => w.message),\n ...(result.warnings ?? [])\n ],\n durationMs: Date.now() - started\n };\n}\n\nconst PX_TO_PT_LOCAL = 72 / 96;\n\nfunction scaleElement(el: LayoutElementLike, scale: number): LayoutElementLike {\n return {\n ...el,\n x: el.x * scale,\n y: el.y * scale,\n width: el.width * scale,\n height: el.height * scale,\n children: (el.children ?? []).map((c) => scaleElement(c, scale))\n };\n}\n\ninterface LayoutElementLike {\n x: number;\n y: number;\n width: number;\n height: number;\n nodeType: string;\n textContent?: string | null;\n children?: LayoutElementLike[];\n}\n\nfunction baseStyle(theme: Theme): unknown {\n return mapStyle({\n fontSize: pxToPt(theme.typography.baseFontSize ?? 11),\n fontFamily: theme.typography.bodyFont.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\")\n } as never);\n}\n\nfunction fontEntries(fonts: FormeFont[]): unknown[] {\n return fonts.map((f) => ({ family: f.family, src: f.src, weight: f.weight ?? 400, style: f.style ?? \"normal\" }));\n}\n\nexport { FormeEditorMeasurer, type FormeEditorMeasurerOptions } from \"./editor.js\";\n","/**\n * Pass 2: draw a document BroadPaper has already paginated.\n *\n * One Forme `Page` per page our paginator decided. Each page places absolutely\n * positioned windows onto the section render — the same model the Chromium\n * backend uses, so the engine makes no layout decisions of its own and every\n * keep-together, orphan/widow and repeated-header choice remains ours.\n *\n * The section is *cropped* to the window before it is drawn, not merely clipped\n * to it: see `clip.ts` for why a clip alone leaves every neighbouring page's\n * text in this page's content stream. The clip stays as well, for the nodes a\n * page genuinely cuts in half.\n */\nimport {\n renderNode,\n walkVNodes,\n type GeometryMap,\n type PagedDocument,\n type PageGeometry,\n type RenderTreeOptions,\n type ResolvedDocument,\n type ResolvedNode,\n type VNode\n} from \"@broadpaper/core\";\nimport { mapStyle } from \"@formepdf/shared\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport { cropToWindow } from \"./clip.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { translate, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { pxToPt, type FormeStyle } from \"./style.js\";\n\n/**\n * An absolutely positioned, optionally clipping box, in CSS pixels.\n *\n * `bleed` widens the box to the right without moving anything inside it. The\n * clip's job is vertical — it is the window onto the page — and clipping\n * horizontally at the content edge only ever cuts a word in half. The engine\n * occasionally sets a line a point or two wider than the box it was given\n * (most often when the theme names a font it does not have and it falls back),\n * and a word spilling a little into the margin reads as a tight line, whereas\n * the same word sliced down the middle reads as a broken renderer.\n */\nfunction box(left: number, top: number, width: number, height: number, children: FormeNode[], clip = true, bleed = 0): FormeNode {\n const style = mapStyle({\n position: \"absolute\",\n left: pxToPt(left),\n top: pxToPt(top),\n width: pxToPt(width + bleed),\n height: pxToPt(height),\n ...(clip ? { overflow: \"hidden\" } : {})\n } as never) as FormeStyle;\n return { kind: { type: \"View\" }, style, children };\n}\n\n/** Strips a rendered table down to its header rows, for repeating across pages. */\nfunction headerOnly(v: VNode): VNode {\n const clone: VNode = structuredClone(v);\n walkVNodes(clone, (n) => {\n if (n.tag === \"table\") {\n n.children = n.children.filter((c) => typeof c !== \"string\" && (c.tag === \"colgroup\" || c.tag === \"thead\"));\n return false;\n }\n return true;\n });\n return clone;\n}\n\nexport interface PagedEmitInput {\n resolved: ResolvedDocument;\n paged: PagedDocument;\n page: PageGeometry;\n renderOpts: RenderTreeOptions;\n ctx: TranslateContext;\n /** The geometry the paginator broke pages with. Drives cropping too, so the\n * two can never disagree about where a page's window falls. */\n geometry: GeometryMap;\n /** Page background, already resolved to a concrete colour. */\n background?: string;\n /**\n * The evaluation mark, or null when the licence says the output is clean.\n * One node per page: this path emits its own pages, so the engine's habit of\n * repeating a watermark across the pages it paginated does not apply.\n */\n watermark?: WatermarkSpec | null;\n}\n\nfunction sectionsByKey(doc: ResolvedDocument): Map<string, ResolvedNode> {\n const map = new Map<string, ResolvedNode>();\n const visit = (n: ResolvedNode) => {\n map.set(n.key, n);\n n.children.forEach(visit);\n };\n for (const list of [doc.body, doc.header.default, doc.header.firstPage ?? [], doc.footer.default, doc.footer.firstPage ?? []]) list.forEach(visit);\n return map;\n}\n\nfunction isPageDependent(nodes: ResolvedNode[]): boolean {\n const check = (n: ResolvedNode): boolean => n.pageDependent === true || n.children.some(check);\n return nodes.some(check);\n}\n\n/** Emits the Forme `Page` nodes for an already-paginated document. */\nexport function emitPages(input: PagedEmitInput): FormeNode[] {\n const { resolved, paged, page, renderOpts, ctx, geometry } = input;\n const byKey = sectionsByKey(resolved);\n const width = page.contentWidth;\n\n // Body content is normally page-independent, so a section rendered for one\n // window can be reused for an identical window on another page; only\n // re-render when a block reads `page.*`.\n // How far content may spill past the content box before the page cuts it:\n // as far as the right margin, and no further.\n const bleed = page.margins.right;\n const bodyDependsOnPage = isPageDependent(resolved.body);\n const cache = new Map<string, { node: FormeNode; offset: number }>();\n const translateSection = (section: ResolvedNode, opts: RenderTreeOptions, from: number, to: number): { node: FormeNode; offset: number } | null => {\n const cacheKey = `${section.key}|${from}|${to}`;\n if (!bodyDependsOnPage && cache.has(cacheKey)) return cache.get(cacheKey)!;\n const v = renderNode(section, opts, width);\n if (!v) return null;\n const geom = geometry[section.key];\n const cropped = geom ? cropToWindow(v, geom, from, to) : { node: v, offset: 0 };\n const t = translate(cropped.node, ctx);\n if (!t) return null;\n const out = { node: t.node, offset: cropped.offset };\n if (!bodyDependsOnPage) cache.set(cacheKey, out);\n return out;\n };\n\n const region = (sections: ResolvedNode[], opts: RenderTreeOptions): FormeNode[] => {\n const out: FormeNode[] = [];\n for (const s of sections) {\n const v = renderNode(s, opts, width);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) out.push(t.node);\n }\n return out;\n };\n\n return paged.pages.map((p) => {\n const opts: RenderTreeOptions = { ...renderOpts, page: { number: p.number, total: paged.totalPages } };\n const children: FormeNode[] = [];\n // Before the content, so the mark is under the report and not across it.\n if (input.watermark) children.push(watermarkNode(input.watermark));\n\n const headerSections = p.first && resolved.header.firstPage ? resolved.header.firstPage : resolved.header.default;\n if (headerSections.length && page.headerHeight > 0) {\n children.push(box(page.margins.left, page.headerTop, width, page.headerHeight, region(headerSections, opts)));\n }\n\n const fragments: FormeNode[] = [];\n for (const f of p.fragments) {\n const section = byKey.get(f.sectionKey);\n if (!section) continue;\n const extra = f.repeatHeaders.reduce((a, r) => a + r.height, 0);\n const inner: FormeNode[] = [];\n\n for (const r of f.repeatHeaders) {\n const table = byKey.get(r.tableKey);\n if (!table) continue;\n const v = renderNode(table, opts, r.width);\n if (!v) continue;\n const t = translate(headerOnly(v), ctx);\n if (t) inner.push(box(r.left, 0, r.width, r.height, [t.node]));\n }\n\n const content = translateSection(section, opts, f.from, f.to);\n if (content) {\n // The window shows [from, to) of the section, so the content is shifted\n // up by `from` to bring that slice into the box. Cropping a cut table\n // to its visible rows makes everything from the table onward sit\n // `offset` higher than the geometry says, so the shift gives that back.\n // Everything else outside the window has been cropped away, and only\n // nodes the window genuinely cuts still rely on the clip.\n const shifted: FormeNode = {\n kind: { type: \"View\" },\n style: mapStyle({ position: \"absolute\", left: 0, top: pxToPt(content.offset - f.from), width: pxToPt(width) } as never) as FormeStyle,\n children: [content.node]\n };\n inner.push(box(0, extra, width, f.to - f.from, [shifted], true, bleed));\n }\n fragments.push(box(0, f.y, width, f.height, inner, true, bleed));\n }\n children.push(box(page.margins.left, page.contentTop, width, page.contentHeight, fragments, true, bleed));\n\n const footerSections = p.first && resolved.footer.firstPage ? resolved.footer.firstPage : resolved.footer.default;\n if (footerSections.length && page.footerHeight > 0) {\n children.push(box(page.margins.left, page.footerTop, width, page.footerHeight, region(footerSections, opts)));\n }\n\n return {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(page.width), height: pxToPt(page.height) } },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n // Nothing may reflow: this page is exactly what the paginator decided.\n wrap: false\n }\n },\n style: input.background ? (mapStyle({ backgroundColor: input.background } as never) as FormeStyle) : {},\n children\n };\n });\n}\n","/**\n * Cropping a section's render down to the window a single page shows.\n *\n * A page draws its share of a section by shifting the whole section up and\n * clipping. Clipping is a graphics-state operation: it hides ink, but the text\n * is still in that page's content stream. Extractors that do not model clip\n * paths — pdf.js and Poppler, which is most of the ecosystem — therefore report\n * a page's text as including its neighbours', so copying a page out of the PDF\n * yields text the reader cannot see, and a screen reader reads a page three\n * times over. It also means every page carries the whole document's ink at\n * coordinates far outside the media box, which is exactly the construct\n * renderers disagree about.\n *\n * There is a second, louder reason. The engine will not lay anything out taller\n * than the page it is drawn on: a table, a text block or a plain box that\n * overflows is truncated, whatever box it sits in and whatever the overflow\n * says. Handing it a hundred-row table and asking for rows 40-80 drew the first\n * ten and dropped the rest. Nothing this module produces may be taller than a\n * page.\n *\n * So content is cropped before it is drawn:\n *\n * - A node wholly outside the window becomes an empty box of exactly the height\n * it measured, which leaves the layout the paginator decided untouched.\n * - A table the window cuts keeps only the rows the window shows. That makes\n * the table shorter than it was, so everything from the table onward moves up\n * by however much was dropped above the window — one number, reported back as\n * `offset` so the page can take it off the shift it was going to apply.\n *\n * Cropping is driven by the same geometry the paginator broke pages with, so\n * the two can never disagree about where a page's window falls.\n */\nimport type { SectionGeometry, TableRowGeometry, VNode } from \"@broadpaper/core\";\nimport { styleString } from \"@broadpaper/core\";\n\nconst EPS = 0.01;\n\ninterface Window {\n geom: SectionGeometry;\n from: number;\n to: number;\n /** Height removed from above the window, which the caller must compensate. */\n dropped: number;\n}\n\nexport interface Cropped {\n node: VNode;\n /**\n * How much shorter the content above the window is now. Everything from that\n * point on sits this many pixels higher than the geometry says, so a page\n * drawing this must shift by `from - offset` rather than by `from`.\n */\n offset: number;\n}\n\n/** Returns `root` cropped to `[from, to)`. The input is not mutated. */\nexport function cropToWindow(root: VNode, geom: SectionGeometry, from: number, to: number): Cropped {\n const w: Window = { geom, from, to, dropped: 0 };\n const node = crop(root, w, undefined);\n return { node, offset: w.dropped };\n}\n\nfunction outside(w: Window, top: number, height: number): boolean {\n return top + height <= w.from + EPS || top >= w.to - EPS;\n}\n\nfunction crop(v: VNode, w: Window, rows: TableRowGeometry[] | undefined): VNode {\n const key = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : undefined;\n const g = key ? w.geom.nodes[key] : undefined;\n if (g) {\n if (outside(w, g.top, g.height)) return blank(v, g.height);\n // A block that measured table rows carries them on its own wrapper, so the\n // rows travel down to whichever descendant is the actual `<table>`.\n if (g.rows) rows = g.rows;\n }\n\n if (v.tag === \"table\" && rows) return cropTable(v, w, rows);\n\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = crop(c, w, rows);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n}\n\n/**\n * Replaces a node with an empty box the same height, keeping the margins that\n * decide where its siblings sit.\n */\nfunction blank(v: VNode, height: number): VNode {\n const kept = styleString(v.props.style)\n .split(\";\")\n .map((d) => d.trim())\n .filter((d) => d && !/^height\\s*:/i.test(d));\n kept.push(`height:${round(height)}px`);\n return { ...v, props: { ...v.props, style: kept.join(\";\") }, children: [] };\n}\n\n/**\n * Keeps only the rows the window shows.\n *\n * Row geometry is recorded in emission order and the translator walks\n * `thead`/`tbody`/`tfoot` in document order, so the two line up by index.\n * Dropping rows rather than blanking them is what keeps the table inside a\n * page's worth of height; the rows dropped from above the window are added to\n * `w.dropped`, because everything below them — including whatever follows the\n * table on this page — has moved up by exactly that much.\n *\n * At most one table per fragment can be cut: a window is contiguous, so any\n * other table in the section is wholly inside it or wholly outside it, and a\n * wholly-outside one has already been blanked by its block wrapper.\n */\nfunction cropTable(table: VNode, w: Window, rows: TableRowGeometry[]): VNode {\n if (rows.length === 0) return table;\n const keep = rows.map((r) => !outside(w, r.top, r.height));\n if (keep.every(Boolean)) return table;\n\n const first = keep.indexOf(true);\n // Nothing of this table is on this page: an empty table draws nothing, and\n // whatever follows it is off the window too.\n if (first === -1) return { tag: \"div\", props: { style: \"height:0\" }, children: [] };\n w.dropped += rows[first]!.top - rows[0]!.top;\n\n let index = 0;\n const rewrite = (node: VNode): VNode | null => {\n const children: Array<VNode | string> = [];\n for (const c of node.children) {\n if (typeof c === \"string\") continue;\n if (c.tag === \"thead\" || c.tag === \"tbody\" || c.tag === \"tfoot\") {\n const next = rewrite(c);\n if (next) children.push(next);\n } else if (c.tag === \"tr\") {\n if (keep[index++]) children.push(c);\n } else children.push(c);\n }\n // A `tbody` left with no rows would still be emitted; drop it. The table\n // itself is kept even when empty, so its column widths survive.\n if (node !== table && !children.some((c) => typeof c !== \"string\" && c.tag === \"tr\")) return null;\n return { ...node, children };\n };\n\n return rewrite(table)!;\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n"],"mappings":"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","names":["kept","box","blank","mapStyle","round","renderNode","mapStyle","resolveLicenseStatus","renderNode","walkVNodes","mapStyle","styleString","round","mapStyle","walkVNodes","renderNode","translate","renderNode","mapStyle","doc","result","pages","scale"]}
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Annotation, EngineLoader, FormeEditorMeasurer, FormeEditorMeasurerOptions, FormeFont, FormeMeasurer, FormeMeasurerOptions, FormeNode, FormePageInfo, FormeRenderer, LayoutElement, LayoutPage, PX_TO_PT, RenderFormePdfOptions, RenderFormePdfResult, RenderPaginatedResult, TranslateContext, Translated, UNBOUNDED_PAGE_HEIGHT, buildFormeDocument, geometryFromLayout, parseDeclarations, pxToPt, renderPdf, renderPdfPaginated, setEngineLoader, translate, translateStyle, vnodeToForme, watermarkNode } from './index.js';
|
|
2
|
-
export { BroadPaper, BroadPaperConfig,
|
|
2
|
+
export { BroadPaper, BroadPaperConfig, LicensePayload, LicenseState, LicenseStatus, LicenseType, Plan, configure, parseLicense, resolveLicenseStatus, verifyLicense } from '@broadpaper/license';
|
|
3
3
|
import '@broadpaper/core';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.browser.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableRowGeometry, BlockRegistry, Theme, DocumentStyles, FormatContext, RenderMode, ResolvedNode, GeometryMap, VNode, RenderTreeOptions, ReportTemplate, AnyVersionTemplate, ReportData, DataSource, PagedDocument } from '@broadpaper/core';
|
|
2
2
|
import { WatermarkSpec, LicenseStatus } from '@broadpaper/license';
|
|
3
|
-
export { BroadPaper, BroadPaperConfig,
|
|
3
|
+
export { BroadPaper, BroadPaperConfig, LicensePayload, LicenseState, LicenseStatus, LicenseType, Plan, configure, parseLicense, resolveLicenseStatus, verifyLicense } from '@broadpaper/license';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Translates the inline CSS our block renderers emit into Forme's style model.
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@broadpaper/forme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Browserless PDF backend for BroadPaper, built on the Forme (Rust/WASM) engine. Runs in Node, edge runtimes and the browser.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@formepdf/core": "^0.20.0",
|
|
31
31
|
"@formepdf/shared": "^0.20.0",
|
|
32
|
-
"@broadpaper/blocks": "0.
|
|
33
|
-
"@broadpaper/core": "0.
|
|
34
|
-
"@broadpaper/license": "0.
|
|
32
|
+
"@broadpaper/blocks": "0.2.0",
|
|
33
|
+
"@broadpaper/core": "0.2.0",
|
|
34
|
+
"@broadpaper/license": "0.2.0"
|
|
35
35
|
},
|
|
36
36
|
"browser": "./dist/index.browser.js",
|
|
37
37
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/style.ts","../src/vnode.ts","../src/svg.ts","../src/watermark.ts","../src/measure.ts","../src/editor.ts","../src/api.ts","../src/paged.ts","../src/clip.ts"],"sourcesContent":["/**\n * Translates the inline CSS our block renderers emit into Forme's style model.\n *\n * BroadPaper blocks produce a deliberately small, self-generated CSS vocabulary\n * (we never accept CSS from users), which is what makes a faithful mapping\n * possible at all. Anything outside that vocabulary is reported rather than\n * dropped silently — the caller surfaces it as a validation warning.\n */\n\n/** CSS pixels at 96 dpi → PDF points at 72 dpi. */\nexport const PX_TO_PT = 72 / 96;\n\nexport function pxToPt(px: number): number {\n return Math.round(px * PX_TO_PT * 1000) / 1000;\n}\n\nexport interface FormeStyle {\n [prop: string]: unknown;\n}\n\nexport interface StyleTranslation {\n style: FormeStyle;\n /** CSS declarations with no Forme equivalent, e.g. \"box-shadow\". */\n unsupported: string[];\n}\n\n/** Parses an inline style string or object into kebab-case declarations. */\nexport function parseDeclarations(style: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (!style) return out;\n if (typeof style === \"object\") {\n for (const [k, v] of Object.entries(style as Record<string, unknown>)) {\n if (v === undefined || v === null || v === \"\") continue;\n out[kebab(k)] = String(v);\n }\n return out;\n }\n for (const decl of String(style).split(\";\")) {\n const i = decl.indexOf(\":\");\n if (i < 0) continue;\n const k = decl.slice(0, i).trim();\n const v = decl.slice(i + 1).trim();\n if (k && v) out[k] = v;\n }\n return out;\n}\n\nfunction kebab(s: string): string {\n return s.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n}\n\n/** \"12px\" → 9 (pt); \"50%\" → \"50%\"; \"auto\" → undefined. */\nexport function length(value: string): number | string | undefined {\n const v = value.trim();\n if (v === \"auto\" || v === \"none\" || v === \"inherit\") return undefined;\n if (v.endsWith(\"%\")) return v;\n const n = Number.parseFloat(v);\n if (!Number.isFinite(n)) return undefined;\n if (v.endsWith(\"em\")) return undefined; // resolved against font size we do not track here\n return pxToPt(n);\n}\n\nfunction num(value: string): number | undefined {\n const n = Number.parseFloat(value);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/** Normalises a CSS colour to `#rrggbb` / `rgba()` that Forme's parser accepts. */\nexport function colour(value: string): string | undefined {\n const v = value.trim().toLowerCase();\n if (!v || v === \"transparent\" || v === \"none\" || v === \"inherit\" || v === \"currentcolor\") return undefined;\n return v;\n}\n\nconst EDGE_ORDER = [\"top\", \"right\", \"bottom\", \"left\"] as const;\n\n/** \"4px 8px\" → { top: 3, right: 6, bottom: 3, left: 6 } in points. */\nexport function edges(value: string): { top: number; right: number; bottom: number; left: number } | undefined {\n const parts = value.trim().split(/\\s+/).map((p) => length(p));\n if (parts.some((p) => typeof p !== \"number\")) return undefined;\n const n = parts as number[];\n const [t, r, b, l] = n.length === 1 ? [n[0]!, n[0]!, n[0]!, n[0]!] : n.length === 2 ? [n[0]!, n[1]!, n[0]!, n[1]!] : n.length === 3 ? [n[0]!, n[1]!, n[2]!, n[1]!] : [n[0]!, n[1]!, n[2]!, n[3]!];\n return { top: t, right: r, bottom: b, left: l };\n}\n\n/** \"1px solid #E2E5EA\" → { width, style, colour }. */\nexport function border(value: string): { width: number; colour?: string } | undefined {\n const v = value.trim();\n if (!v || v === \"none\" || v.startsWith(\"0 \") || v === \"0\") return undefined;\n const widthMatch = /(-?[\\d.]+)px/.exec(v);\n const colourMatch = /(#[0-9a-f]{3,8}|rgba?\\([^)]+\\))/i.exec(v);\n const width = widthMatch ? pxToPt(Number(widthMatch[1])) : 0.75;\n if (/\\bnone\\b/.test(v)) return undefined;\n return { width, colour: colourMatch ? colourMatch[0] : undefined };\n}\n\nconst FLEX_DIRECTION: Record<string, string> = { row: \"row\", column: \"column\", \"row-reverse\": \"row-reverse\", \"column-reverse\": \"column-reverse\" };\nconst JUSTIFY: Record<string, string> = { \"flex-start\": \"flex-start\", start: \"flex-start\", \"flex-end\": \"flex-end\", end: \"flex-end\", center: \"center\", \"space-between\": \"space-between\", \"space-around\": \"space-around\", \"space-evenly\": \"space-evenly\" };\nconst ALIGN: Record<string, string> = { \"flex-start\": \"flex-start\", start: \"flex-start\", \"flex-end\": \"flex-end\", end: \"flex-end\", center: \"center\", stretch: \"stretch\", baseline: \"baseline\" };\nconst TEXT_ALIGN: Record<string, string> = { left: \"left\", right: \"right\", center: \"center\", justify: \"justify\" };\n\n/** Declarations we knowingly ignore because they have no bearing on PDF output. */\nconst IGNORED = new Set([\n \"box-sizing\", \"-webkit-font-smoothing\", \"text-rendering\", \"font-variant-numeric\", \"pointer-events\",\n \"user-select\", \"cursor\", \"text-overflow\", \"white-space\", \"word-wrap\", \"overflow-wrap\", \"box-decoration-break\",\n \"-webkit-box-decoration-break\", \"text-underline-offset\", \"text-decoration-thickness\", \"outline\", \"transition\",\n \"list-style\", \"border-collapse\", \"border-spacing\", \"table-layout\", \"vertical-align\", \"min-width\", \"max-width\",\n \"-webkit-line-clamp\", \"-webkit-box-orient\", \"object-fit\", \"content\", \"zoom\", \"transform-origin\"\n]);\n\n/**\n * Maps CSS declarations to Forme style props. Returns the props plus any\n * declaration we could not represent.\n */\nexport function translateStyle(css: Record<string, string>): StyleTranslation {\n const s: FormeStyle = {};\n const unsupported: string[] = [];\n const set = (k: string, v: unknown) => {\n if (v !== undefined) s[k] = v;\n };\n\n for (const [prop, raw] of Object.entries(css)) {\n const value = raw.trim();\n if (IGNORED.has(prop)) continue;\n switch (prop) {\n case \"display\":\n if (value === \"flex\" || value === \"inline-flex\") set(\"display\", \"flex\");\n else if (value === \"grid\") {\n // Our only grids are equal-track column layouts; flex row reproduces\n // them exactly and is honoured by the engine. Whether the row wraps\n // depends on the child count, which the translator decides.\n set(\"display\", \"flex\");\n set(\"flexDirection\", \"row\");\n } else if (value === \"none\") set(\"display\", \"none\");\n break;\n case \"flex-direction\":\n set(\"flexDirection\", FLEX_DIRECTION[value]);\n break;\n case \"justify-content\":\n set(\"justifyContent\", JUSTIFY[value]);\n break;\n case \"align-items\":\n set(\"alignItems\", ALIGN[value]);\n break;\n case \"align-self\":\n set(\"alignSelf\", ALIGN[value]);\n break;\n case \"flex-wrap\":\n set(\"flexWrap\", value === \"wrap\" ? \"wrap\" : \"nowrap\");\n break;\n case \"flex\":\n set(\"flexGrow\", num(value.split(/\\s+/)[0] ?? \"0\"));\n break;\n case \"flex-grow\":\n set(\"flexGrow\", num(value));\n break;\n case \"flex-shrink\":\n set(\"flexShrink\", num(value));\n break;\n case \"gap\":\n case \"row-gap\":\n case \"column-gap\": {\n const parts = value.split(/\\s+/).map((p) => length(p));\n const first = typeof parts[0] === \"number\" ? parts[0] : undefined;\n const second = parts.length > 1 && typeof parts[1] === \"number\" ? parts[1] : first;\n if (prop === \"gap\") {\n set(\"rowGap\", first);\n set(\"columnGap\", second);\n } else set(prop === \"row-gap\" ? \"rowGap\" : \"columnGap\", first);\n break;\n }\n case \"grid-template-columns\":\n // Track count is recovered by the translator, which turns our 12-track\n // rows into proportional flex children.\n break;\n case \"grid-column\": {\n // \"span 6\" of 12 tracks: grow in proportion to the span.\n const span = /^span\\s+(\\d+)$/.exec(value);\n if (span) {\n set(\"flexGrow\", Number(span[1]));\n set(\"flexBasis\", 0);\n }\n break;\n }\n case \"width\":\n set(\"width\", length(value));\n break;\n case \"height\": {\n // A percentage height is a CSS-ism for \"fill the row\"; in a flow layout\n // it has no meaningful referent, and the engine resolves it to points,\n // which would inflate every row it appears on. Flex stretch covers it.\n const h = length(value);\n if (typeof h === \"number\") set(\"height\", h);\n break;\n }\n case \"padding\":\n set(\"padding\", edges(value));\n break;\n case \"padding-top\":\n case \"padding-right\":\n case \"padding-bottom\":\n case \"padding-left\":\n set(`padding${cap(prop.slice(8))}`, length(value));\n break;\n case \"margin\":\n set(\"margin\", edges(value));\n break;\n case \"margin-top\":\n case \"margin-right\":\n case \"margin-bottom\":\n case \"margin-left\":\n set(`margin${cap(prop.slice(7))}`, length(value));\n break;\n case \"background\":\n case \"background-color\":\n set(\"backgroundColor\", colour(value));\n break;\n case \"color\":\n set(\"color\", colour(value));\n break;\n case \"font-family\":\n set(\"fontFamily\", value.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\"));\n break;\n case \"font-size\":\n set(\"fontSize\", length(value));\n break;\n case \"font-weight\":\n set(\"fontWeight\", value === \"bold\" ? 700 : value === \"normal\" ? 400 : num(value));\n break;\n case \"font-style\":\n if (value === \"italic\") set(\"fontStyle\", \"italic\");\n break;\n case \"line-height\":\n set(\"lineHeight\", num(value));\n break;\n case \"letter-spacing\":\n if (value.endsWith(\"px\")) set(\"letterSpacing\", length(value));\n break;\n case \"text-align\":\n set(\"textAlign\", TEXT_ALIGN[value]);\n break;\n case \"text-transform\":\n if (value !== \"none\") set(\"textTransform\", value);\n break;\n case \"text-decoration\":\n if (value.includes(\"underline\")) set(\"textDecoration\", \"underline\");\n else if (value.includes(\"line-through\")) set(\"textDecoration\", \"line-through\");\n break;\n case \"opacity\":\n set(\"opacity\", num(value));\n break;\n case \"overflow\":\n if (value === \"hidden\") set(\"overflow\", \"hidden\");\n break;\n case \"border-radius\": {\n const r = length(value.split(/\\s+/)[0] ?? \"0\");\n set(\"borderRadius\", typeof r === \"number\" ? r : undefined);\n break;\n }\n case \"border\": {\n const b = border(value);\n if (b) {\n set(\"borderWidth\", b.width);\n set(\"borderColor\", b.colour);\n }\n break;\n }\n case \"border-top\":\n case \"border-right\":\n case \"border-bottom\":\n case \"border-left\": {\n const side = cap(prop.slice(7));\n const b = border(value);\n if (b) {\n set(`border${side}Width`, b.width);\n set(`border${side}Color`, b.colour);\n }\n break;\n }\n case \"position\":\n // Relative matters as much as absolute: it is what makes a box the\n // frame its absolutely positioned children are measured from.\n if (value === \"absolute\" || value === \"relative\") set(\"position\", value);\n break;\n case \"top\":\n case \"left\":\n case \"right\":\n case \"bottom\":\n set(prop, length(value));\n break;\n default:\n unsupported.push(prop);\n }\n }\n // CSS defaults `flex-direction` to row; the engine's React-Native-flavoured\n // model defaults to column. Without this every unqualified `display: flex`\n // silently stacks — the single largest source of layout drift we found.\n if (s.display === \"flex\" && s.flexDirection === undefined) s.flexDirection = \"row\";\n return { style: s, unsupported };\n}\n\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","/**\n * VNode → Forme document node.\n *\n * Block renderers (built-in and custom alike) return a VNode tree, so a single\n * translator gives every block a browserless PDF path for free — no block has\n * to know Forme exists.\n *\n * Alongside each emitted node the translator records an `Annotation` in exactly\n * the same shape. That is what lets `measure.ts` map Forme's layout result back\n * onto BroadPaper node keys without the engine needing to carry our identifiers.\n */\nimport { classNames, styleString, toHtml, walkVNodes, type VNode } from \"@broadpaper/core\";\nimport { mapStyle, mapColumnWidth } from \"@formepdf/shared\";\nimport { parseDeclarations, translateStyle, length, pxToPt, type FormeStyle } from \"./style.js\";\nimport { splitSvg, svgFromDataUri, type SvgLabel } from \"./svg.js\";\nimport type { Annotation } from \"./measure.js\";\n\nexport interface FormeNode {\n kind: Record<string, unknown>;\n style: FormeStyle;\n children: FormeNode[];\n href?: string;\n alt?: string;\n}\n\nexport interface TranslateContext {\n warnings: Set<string>;\n /**\n * Keeps design-mode affordances — placeholders, empty-slot outlines, the\n * page-break rule. They never belong in a PDF, but when this translation is\n * measuring the editor's canvas they are part of what the canvas draws, and\n * measuring them as nothing makes blocks invisible on screen.\n */\n design?: boolean;\n /**\n * Drops page-break nodes, for the passes where BroadPaper has already decided\n * the pages. Measurement uses one unbounded page and reads back only its\n * first, so a break there would silently discard everything after it; the\n * paginated draw pass has placed its content already and must not reflow.\n */\n suppressPageBreaks?: boolean;\n}\n\n/** An emitted node paired with its annotation. */\nexport interface Translated {\n node: FormeNode;\n ann: Annotation;\n}\n\nconst INLINE_TAGS = new Set([\"span\", \"strong\", \"b\", \"em\", \"i\", \"u\", \"s\", \"code\", \"a\", \"small\"]);\nconst TEXT_BLOCK_TAGS = new Set([\"p\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"li\", \"blockquote\", \"figcaption\", \"label\", \"td\", \"th\", \"div\"]);\n\nfunction declarationsOf(v: VNode): Record<string, string> {\n return parseDeclarations(typeof v.props.style === \"string\" ? v.props.style : styleString(v.props.style));\n}\n\nfunction styleOf(v: VNode, ctx: TranslateContext): FormeStyle {\n const decls = declarationsOf(v);\n const { style, unsupported } = translateStyle(decls);\n for (const u of unsupported) ctx.warnings.add(`unsupported CSS property \"${u}\" (ignored)`);\n // Forme's own public mapper produces the engine JSON, so enum spellings and\n // dimension wrappers stay correct as the engine evolves.\n return mapStyle(style as never) as FormeStyle;\n}\n\n/** Flattens an element's descendants into a single string of text. */\nfunction textOf(v: VNode | string): string {\n if (typeof v === \"string\") return v;\n if (v.tag === \"br\") return \"\\n\";\n return v.children.map(textOf).join(\"\");\n}\n\nfunction hasBlockChild(v: VNode): boolean {\n return v.children.some((c) => typeof c !== \"string\" && !INLINE_TAGS.has(c.tag) && c.tag !== \"br\");\n}\n\n/** True when this subtree holds wrapped body text whose line boxes we want. */\nfunction holdsWrappedText(v: VNode): boolean {\n let found = false;\n walkVNodes(v, (n) => {\n if (n.props[\"data-part\"] === \"text\") found = true;\n return !found;\n });\n return found;\n}\n\nfunction leaf(node: FormeNode, ann: Annotation = { children: [] }): Translated {\n return { node, ann };\n}\n\nfunction svgNode(v: VNode, ctx: TranslateContext): Translated {\n const width = Number(v.props.width) || 0;\n const height = Number(v.props.height) || 0;\n // The engine builds its own SVG viewport from width, height and view_box, so\n // `content` is the markup that goes inside it. Handing it a whole <svg>\n // element instead nests one viewport in another: the inner one keeps our\n // pixel dimensions inside an outer one sized in points, and every chart is\n // drawn a third too large and clipped by its box.\n const { markup, labels } = splitSvg(v, (message) => ctx.warnings.add(message));\n const viewBox = typeof v.props.viewBox === \"string\" ? v.props.viewBox : `0 0 ${width} ${height}`;\n // The size goes in the style as well as the kind. Without a box the engine\n // lays the node out as auto and it takes whatever room is going, which turns\n // a 19px trend arrow into a line of its own.\n const box = mapStyle({ width: pxToPt(width), height: pxToPt(height) } as never) as FormeStyle;\n const shapes: FormeNode = {\n kind: { type: \"Svg\", width: pxToPt(width), height: pxToPt(height), view_box: viewBox, content: markup },\n style: { ...box, ...styleOf(v, ctx) },\n children: []\n };\n if (!labels.length) return leaf(shapes);\n\n // The engine does not draw SVG text, so the labels are placed over the chart\n // as real text. Positions come from the view box, which is the coordinate\n // system the labels were written in.\n const vb = viewBox.trim().split(/[\\s,]+/).map(Number);\n const sx = vb.length === 4 && vb[2] ? width / vb[2]! : 1;\n const sy = vb.length === 4 && vb[3] ? height / vb[3]! : 1;\n const children = [shapes, ...labels.map((l) => labelNode(l, sx, sy))];\n return {\n node: {\n kind: { type: \"View\" },\n // Relative, so the labels are placed against this box rather than the page.\n style: mapStyle({ position: \"relative\", width: pxToPt(width), height: pxToPt(height) } as never) as FormeStyle,\n children\n },\n ann: { children: children.map(() => ({ children: [] })) }\n };\n}\n\n/** One SVG label, positioned over the chart it was lifted out of. */\nfunction labelNode(l: SvgLabel, sx: number, sy: number): FormeNode {\n const x = l.x * sx;\n const size = l.fontSize * Math.min(sx, sy);\n // SVG anchors text at a point; the engine positions a box. Without knowing\n // the shaped width we estimate it — 0.55em is close for the sans faces\n // reports use — and place the box so the anchor point lands where the SVG\n // asked. A box wide enough to never wrap but no wider keeps a label from\n // being pushed around inside a small graphic such as a logo.\n const estimate = Math.max(size, l.text.length * size * 0.55);\n const width = estimate * 1.5;\n const left = l.anchor === \"middle\" ? x - estimate / 2 : l.anchor === \"end\" ? x - estimate : x;\n const style: Record<string, unknown> = {\n position: \"absolute\",\n left: pxToPt(left),\n // `y` is a baseline; a box starts roughly one ascender higher.\n top: pxToPt(l.y * sy - size * 0.8),\n width: pxToPt(width),\n fontSize: pxToPt(size),\n textAlign: \"left\"\n };\n if (l.fill) style.color = l.fill;\n if (l.fontFamily) style.fontFamily = l.fontFamily.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\");\n if (l.fontWeight) style.fontWeight = l.fontWeight;\n return { kind: { type: \"Text\", content: l.text }, style: mapStyle(style as never) as FormeStyle, children: [] };\n}\n\n/**\n * The size an inline SVG should be drawn at.\n *\n * An `<img>` is usually sized by CSS rather than by the artwork, so a logo\n * styled to 28px tall must be drawn at 28px tall and not at its intrinsic 48.\n * The aspect ratio comes from the artwork whenever only one dimension is given.\n */\nfunction sizeFrom(img: VNode, svg: VNode): { width: number; height: number } {\n const own = { width: Number(svg.props.width) || 0, height: Number(svg.props.height) || 0 };\n const box = String(svg.props.viewBox ?? \"\").trim().split(/[\\s,]+/).map(Number);\n const natural = {\n width: own.width || (box.length === 4 ? box[2]! : 0),\n height: own.height || (box.length === 4 ? box[3]! : 0)\n };\n const css = parseDeclarations(typeof img.props.style === \"string\" ? img.props.style : styleString(img.props.style));\n const asked = { width: Number.parseFloat(css.width ?? \"\"), height: Number.parseFloat(css.height ?? \"\") };\n const ratio = natural.width && natural.height ? natural.width / natural.height : 0;\n\n let width = Number.isFinite(asked.width) ? asked.width : 0;\n let height = Number.isFinite(asked.height) ? asked.height : 0;\n if (!width && height && ratio) width = height * ratio;\n if (!height && width && ratio) height = width / ratio;\n return { width: width || natural.width, height: height || natural.height };\n}\n\nfunction tableNode(v: VNode, ctx: TranslateContext): Translated {\n const columns: Array<{ width: unknown }> = [];\n const rows: FormeNode[] = [];\n const rowAnns: Annotation[] = [];\n const rowKinds: Array<\"header\" | \"body\" | \"footer\"> = [];\n\n const visit = (node: VNode, kind: \"header\" | \"body\" | \"footer\") => {\n for (const child of node.children) {\n if (typeof child === \"string\") continue;\n if (child.tag === \"colgroup\") {\n for (const col of child.children) {\n if (typeof col === \"string\") continue;\n const w = parseDeclarations(typeof col.props.style === \"string\" ? col.props.style : styleString(col.props.style)).width;\n const parsed = w ? length(w) : undefined;\n // Forme sizes table columns by fraction or fixed points; our percentage\n // widths become fractions of the table width.\n columns.push({\n width: mapColumnWidth(\n typeof parsed === \"string\" ? { fraction: Number.parseFloat(parsed) / 100 } : typeof parsed === \"number\" ? { fixed: parsed } : \"auto\"\n )\n });\n }\n } else if (child.tag === \"thead\") visit(child, \"header\");\n else if (child.tag === \"tbody\") visit(child, \"body\");\n else if (child.tag === \"tfoot\") visit(child, \"footer\");\n else if (child.tag === \"tr\") {\n const cells: FormeNode[] = [];\n const cellAnns: Annotation[] = [];\n for (const cell of child.children) {\n if (typeof cell === \"string\") continue;\n const inner = childNodes(cell, ctx);\n cells.push({\n kind: { type: \"TableCell\", col_span: Number(cell.props.colspan) || 1, row_span: Number(cell.props.rowspan) || 1 },\n style: styleOf(cell, ctx),\n children: inner.nodes\n });\n cellAnns.push({ children: inner.anns });\n }\n rows.push({ kind: { type: \"TableRow\", is_header: kind === \"header\" }, style: styleOf(child, ctx), children: cells });\n rowAnns.push({ children: cellAnns });\n rowKinds.push(kind);\n }\n }\n };\n visit(v, \"body\");\n return {\n node: { kind: { type: \"Table\", columns }, style: styleOf(v, ctx), children: rows },\n ann: { rowKinds, children: rowAnns }\n };\n}\n\n/** Style props that describe glyphs rather than the box around them. */\nconst TEXT_PROPS = [\"color\", \"fontFamily\", \"fontSize\", \"fontWeight\", \"fontStyle\", \"lineHeight\", \"letterSpacing\", \"textAlign\", \"textTransform\", \"textDecoration\"] as const;\n\nfunction textStyleOf(style: FormeStyle): FormeStyle {\n const out: FormeStyle = {};\n for (const k of TEXT_PROPS) if (style[k] !== undefined) out[k] = style[k];\n return out;\n}\n\nfunction childNodes(v: VNode, ctx: TranslateContext, inherited: FormeStyle = {}): { nodes: FormeNode[]; anns: Annotation[] } {\n const nodes: FormeNode[] = [];\n const anns: Annotation[] = [];\n for (const child of v.children) {\n if (typeof child === \"string\") {\n if (!child.trim()) continue;\n // The engine's model is React-Native-flavoured: a view's font and colour\n // do not reach a text node inside it, so they are copied down.\n nodes.push({ kind: { type: \"Text\", content: child }, style: inherited, children: [] });\n anns.push({ children: [] });\n continue;\n }\n const t = translate(child, ctx);\n if (!t) continue;\n nodes.push(t.node);\n anns.push(t.ann);\n }\n return { nodes, anns };\n}\n\n/** Translates one VNode, returning the emitted node and its annotation. */\nexport function translate(v: VNode, ctx: TranslateContext): Translated | null {\n const cls = classNames(v.props.class);\n // Design-mode affordances never belong in a PDF, but they do belong in a\n // measurement of the design canvas, which draws them.\n if (!ctx.design && /bp-(placeholder|empty-section|empty-column)\\b/.test(cls)) return null;\n if (/bp-page-break\\b/.test(cls) && !ctx.suppressPageBreaks) return leaf({ kind: { type: \"PageBreak\" }, style: {}, children: [] });\n\n let result: Translated | null;\n switch (v.tag) {\n case \"svg\":\n result = svgNode(v, ctx);\n break;\n case \"table\":\n result = tableNode(v, ctx);\n break;\n case \"img\": {\n const src = typeof v.props.src === \"string\" ? v.props.src : \"\";\n if (!src) return null;\n // An SVG data URI is vector artwork, not a bitmap. The engine's image\n // decoder cannot read one and leaves a grey box where the logo should be,\n // so treat it as the drawing it is.\n const vector = svgFromDataUri(src);\n if (vector) {\n const sized: VNode = { ...vector, props: { ...vector.props, ...sizeFrom(v, vector) } };\n result = svgNode(sized, ctx);\n break;\n }\n const node: FormeNode = { kind: { type: \"Image\", src }, style: styleOf(v, ctx), children: [] };\n if (typeof v.props.alt === \"string\" && v.props.alt) node.alt = v.props.alt;\n result = leaf(node);\n break;\n }\n case \"br\":\n result = leaf({ kind: { type: \"Text\", content: \"\\n\" }, style: {}, children: [] });\n break;\n case \"ul\":\n case \"ol\": {\n const items: FormeNode[] = [];\n const itemAnns: Annotation[] = [];\n for (const li of v.children) {\n if (typeof li === \"string\") continue;\n const inner = childNodes(li, ctx);\n items.push({ kind: { type: \"ListItem\" }, style: styleOf(li, ctx), children: inner.nodes });\n itemAnns.push({ children: inner.anns });\n }\n result = {\n // Marker names are the CSS `list-style-type` spellings, not capitalised\n // variant names: the engine rejects the whole document over one wrong\n // enum, so a single bullet list used to mean no PDF at all.\n node: { kind: { type: \"List\", ordered: v.tag === \"ol\", marker_type: v.tag === \"ol\" ? \"decimal\" : \"disc\", start: 1 }, style: styleOf(v, ctx), children: items },\n ann: { children: itemAnns }\n };\n break;\n }\n case \"colgroup\":\n case \"col\":\n return null;\n default:\n result = null;\n }\n\n if (!result) {\n const style = styleOf(v, ctx);\n const heading = /^h([1-6])$/.exec(v.tag);\n\n const content = textOf(v);\n const blank = !content.trim();\n if (blank && !Object.keys(style).length && !v.children.length) return null;\n\n // A text block with only inline content becomes one Text node; the inline\n // runs are flattened into it so their content survives.\n //\n // A text node with nothing in it is a different matter. Spacers and\n // dividers are empty `div`s carrying only a height or a border, and the\n // engine gives every Text node a line box — so translating them as text\n // would silently add a line's worth of height that no browser shows. They\n // become plain views instead. An intentionally empty paragraph keeps its\n // blank line, because there the line is the point.\n // An element that lays its children out — flex or grid — is a layout box\n // even when every child is an inline tag, or a bare string. Flattening one\n // into a run of text turns \"Lower risk … Higher risk\" into\n // \"Lower riskHigher risk\", and turns a callout's round badge into a text\n // node that paints neither its background nor its border.\n const decls = declarationsOf(v);\n const laysOut = decls.display === \"flex\" || decls.display === \"inline-flex\" || decls.display === \"grid\";\n const textual = (TEXT_BLOCK_TAGS.has(v.tag) || INLINE_TAGS.has(v.tag) || heading) && !hasBlockChild(v) && !laysOut;\n if (textual && (!blank || /bp-p--empty/.test(cls))) {\n const kind: Record<string, unknown> = heading ? { type: \"Heading\", level: Number(heading[1]), content } : { type: \"Text\", content };\n const node: FormeNode = { kind, style, children: [] };\n if (v.tag === \"a\" && typeof v.props.href === \"string\") node.href = v.props.href;\n result = leaf(node);\n } else {\n const inner = childNodes(v, ctx);\n // An empty view still draws when it carries a rule, a fill or a height —\n // that is exactly what our spacers and dividers are.\n const draws = Object.keys(style).some((k) => /^border[A-Za-z]*Width$/.test(k)) || style.backgroundColor !== undefined || style.height !== undefined;\n if (inner.nodes.length === 0 && !draws) return null;\n if (decls.display === \"grid\") applyGridAsFlex(style, inner.nodes, decls);\n const node: FormeNode = { kind: { type: \"View\" }, style, children: inner.nodes };\n if (v.tag === \"a\" && typeof v.props.href === \"string\") node.href = v.props.href;\n result = { node, ann: { children: inner.anns } };\n }\n }\n\n // Block wrappers carry `data-key`; that is our handle for mapping geometry back.\n const key = v.props[\"data-key\"];\n if (typeof key === \"string\") {\n result.ann.key = key;\n if (holdsWrappedText(v)) result.ann.text = true;\n // A table sits inside its block's wrapper, so lift the row roles onto the\n // keyed node — that is where the paginator looks for them.\n if (!result.ann.rowKinds) {\n const rows = findRowKinds(result.ann);\n if (rows) result.ann.rowKinds = rows;\n }\n }\n return result;\n}\n\n/**\n * Reproduces one of our CSS grids with flexbox.\n *\n * Rows declare twelve tracks and their columns a span, which becomes a\n * proportional `flexGrow`. A grid whose children outnumber its tracks (the\n * key/value grid) genuinely wraps, so it keeps `flexWrap` and a per-track\n * basis; a row that fits on one line must not wrap, or an over-wide child such\n * as a logo pushes the next column onto a second line.\n */\nfunction applyGridAsFlex(style: FormeStyle, children: FormeNode[], decls: Record<string, string>): void {\n const tracks = /repeat\\(\\s*(\\d+)/.exec(decls[\"grid-template-columns\"] ?? \"\");\n const spanned = children.filter((c) => typeof c.style.flexGrow === \"number\" && c.style.flexGrow > 0).length;\n const perRow = tracks && spanned === 0 ? Number(tracks[1]) : children.length;\n const wraps = children.length > perRow;\n style.flexWrap = wraps ? \"Wrap\" : \"NoWrap\";\n for (const child of children) {\n if (child.style.flexGrow === undefined) {\n child.style.flexGrow = 1;\n child.style.flexBasis = wraps ? { Percent: 100 / Math.max(1, perRow) } : { Pt: 0 };\n }\n // Columns must give way rather than overflow: a wide logo or a long word\n // should shrink its column, never push a sibling onto the next line.\n if (child.style.flexShrink === undefined) child.style.flexShrink = 1;\n if (child.style.minWidth === undefined) child.style.minWidth = { Pt: 0 };\n }\n}\n\n/** First `rowKinds` found in a subtree, so a wrapper can adopt its table's rows. */\nfunction findRowKinds(ann: Annotation): Annotation[\"rowKinds\"] | undefined {\n if (ann.rowKinds) return ann.rowKinds;\n for (const c of ann.children) {\n const found = findRowKinds(c);\n if (found) return found;\n }\n return undefined;\n}\n\n/** Translates one VNode. Returns null for nodes that draw nothing. */\nexport function vnodeToForme(v: VNode, ctx: TranslateContext): FormeNode | null {\n return translate(v, ctx)?.node ?? null;\n}\n","/**\n * Bakes `translate(...)` transforms into the coordinates they move.\n *\n * The engine's SVG renderer does not apply transforms on groups. Our charts\n * lean on them heavily — a donut is arcs drawn around the origin and moved to\n * the centre, a legend is rows moved down one line at a time — so without this\n * every one of those pieces lands on top of the origin and the chart is\n * unreadable.\n *\n * Flattening at this boundary rather than in the chart code keeps the charts\n * written the way SVG is normally written, and covers custom blocks that emit\n * SVG of their own. Only translation is flattened; anything else is left in\n * place and reported, because silently drawing it wrong is worse than saying so.\n */\nimport { toHtml, type VNode, type VProps } from \"@broadpaper/core\";\n\n/** Attributes that carry a coordinate, and which axis each one moves along. */\nconst COORDS: Record<string, Array<[attr: string, axis: 0 | 1]>> = {\n rect: [[\"x\", 0], [\"y\", 1]],\n circle: [[\"cx\", 0], [\"cy\", 1]],\n ellipse: [[\"cx\", 0], [\"cy\", 1]],\n line: [[\"x1\", 0], [\"y1\", 1], [\"x2\", 0], [\"y2\", 1]],\n text: [[\"x\", 0], [\"y\", 1]],\n tspan: [[\"x\", 0], [\"y\", 1]],\n image: [[\"x\", 0], [\"y\", 1]],\n use: [[\"x\", 0], [\"y\", 1]]\n};\n\nconst TRANSLATE = /^\\s*translate\\(\\s*(-?[\\d.eE+]+)\\s*(?:[, ]\\s*(-?[\\d.eE+]+))?\\s*\\)\\s*$/;\n\n/** Parses `translate(x, y)`. Returns null for anything else, including no transform. */\nfunction translationOf(value: unknown): [number, number] | null | \"unsupported\" {\n if (typeof value !== \"string\" || !value.trim()) return null;\n const m = TRANSLATE.exec(value);\n if (!m) return \"unsupported\";\n return [Number(m[1]), m[2] === undefined ? 0 : Number(m[2])];\n}\n\n/** Number of parameters each path command takes, and which of them are coordinates. */\nconst PATH_COMMANDS: Record<string, { size: number; coords: number[] }> = {\n m: { size: 2, coords: [0, 1] },\n l: { size: 2, coords: [0, 1] },\n t: { size: 2, coords: [0, 1] },\n h: { size: 1, coords: [0] },\n v: { size: 1, coords: [1] },\n c: { size: 6, coords: [0, 1, 0, 1, 0, 1] },\n s: { size: 4, coords: [0, 1, 0, 1] },\n q: { size: 4, coords: [0, 1, 0, 1] },\n // rx ry rotation large-arc sweep x y — only the final pair is a position.\n a: { size: 7, coords: [-1, -1, -1, -1, -1, 0, 1] },\n z: { size: 0, coords: [] }\n};\n\n/**\n * Shifts a path's absolute coordinates. Relative commands describe deltas and\n * are already correct, except for a leading `m`, which the spec treats as\n * absolute because there is no current point to be relative to.\n */\nexport function translatePathData(d: string, dx: number, dy: number): string {\n if (!dx && !dy) return d;\n const tokens = d.match(/[a-zA-Z]|-?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return d;\n\n const out: string[] = [];\n let command = \"\";\n let i = 0;\n let first = true;\n\n while (i < tokens.length) {\n const token = tokens[i]!;\n if (/[a-zA-Z]/.test(token)) {\n command = token;\n out.push(token);\n i++;\n if (command.toLowerCase() === \"z\") {\n first = false;\n continue;\n }\n }\n const spec = PATH_COMMANDS[command.toLowerCase()];\n if (!spec || spec.size === 0) {\n // A command we do not know: copy the rest through untouched rather than\n // guess at its parameters and corrupt the path.\n while (i < tokens.length) out.push(tokens[i++]!);\n break;\n }\n // An implicit repeat of `M`/`m` continues as `L`/`l`.\n const absolute = command === command.toUpperCase() || (first && command === \"m\");\n for (let p = 0; p < spec.size && i < tokens.length; p++) {\n const axis = spec.coords[p]!;\n const value = Number(tokens[i]!);\n out.push(absolute && axis >= 0 ? String(round(value + (axis === 0 ? dx : dy))) : tokens[i]!);\n i++;\n }\n if (first) {\n first = false;\n if (command === \"m\") command = \"l\";\n else if (command === \"M\") command = \"L\";\n }\n }\n return out.join(\" \");\n}\n\nfunction round(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n\n/** Shifts a `points` list, as used by polyline and polygon. */\nfunction translatePoints(points: string, dx: number, dy: number): string {\n const nums = points.match(/-?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!nums) return points;\n return nums.map((n, i) => round(Number(n) + (i % 2 === 0 ? dx : dy))).join(\" \");\n}\n\nfunction shift(v: VNode, dx: number, dy: number, warn: (message: string) => void): VNode {\n const own = translationOf(v.props.transform);\n let tx = dx;\n let ty = dy;\n const props: VProps = { ...v.props };\n\n if (own === \"unsupported\") {\n warn(`SVG transform \"${String(v.props.transform)}\" is not translate() and was left to the engine, which ignores it`);\n } else if (own) {\n tx += own[0];\n ty += own[1];\n delete props.transform;\n }\n\n if (tx || ty) {\n for (const [attr, axis] of COORDS[v.tag] ?? []) {\n // An absent coordinate defaults to zero, and zero still has to move.\n const current = props[attr] as unknown;\n const base = current === undefined || current === null || current === \"\" ? 0 : Number(current);\n if (Number.isFinite(base)) props[attr] = round(base + (axis === 0 ? tx : ty));\n }\n if (v.tag === \"path\" && typeof props.d === \"string\") props.d = translatePathData(props.d, tx, ty);\n if ((v.tag === \"polyline\" || v.tag === \"polygon\") && typeof props.points === \"string\") props.points = translatePoints(props.points, tx, ty);\n }\n\n const children = v.children.map((c) => (typeof c === \"string\" ? c : shift(c, tx, ty, warn)));\n return { ...v, props, children };\n}\n\n/** A label lifted out of an SVG, in the SVG's own user units. */\nexport interface SvgLabel {\n x: number;\n y: number;\n text: string;\n anchor: \"start\" | \"middle\" | \"end\";\n fontSize: number;\n fontFamily?: string;\n fontWeight?: number;\n fill?: string;\n}\n\nfunction textContent(v: VNode | string): string {\n if (typeof v === \"string\") return v;\n return v.children.map(textContent).join(\"\");\n}\n\nfunction numeric(value: unknown, fallback: number): number {\n const n = typeof value === \"number\" ? value : Number.parseFloat(String(value ?? \"\"));\n return Number.isFinite(n) ? n : fallback;\n}\n\n/**\n * Splits an SVG into the shapes the engine can draw and the labels it cannot.\n *\n * The engine renders paths, rects and circles but not `<text>`, so axis labels,\n * legends and the number in the middle of a donut simply vanish. Lifting them\n * out and drawing them as real text is better than rasterising the chart: the\n * words stay selectable, searchable and available to a screen reader.\n *\n * Coordinates are absolute by this point, because transforms are flattened\n * first. Groups survive as `<g>` so that presentation attributes they carry —\n * fill, stroke, opacity — still inherit to their children.\n */\n/** Attributes a browser uses to make a chart interactive; meaningless in a PDF. */\nconst SCREEN_ONLY = /^data-bp-/;\n\nexport function splitSvg(v: VNode, warn: (message: string) => void): { markup: string; labels: SvgLabel[] } {\n const flat = shift(v, 0, 0, warn);\n const labels: SvgLabel[] = [];\n\n const strip = (node: VNode, inherited: { fontFamily?: string; fill?: string }): VNode | null => {\n const own = {\n fontFamily: (node.props[\"font-family\"] as string | undefined) ?? inherited.fontFamily,\n fill: (node.props.fill as string | undefined) ?? inherited.fill\n };\n if (node.tag === \"text\") {\n const text = textContent(node).trim();\n if (text) {\n const anchor = String(node.props[\"text-anchor\"] ?? \"start\");\n labels.push({\n x: numeric(node.props.x, 0),\n y: numeric(node.props.y, 0),\n text,\n anchor: anchor === \"middle\" || anchor === \"end\" ? anchor : \"start\",\n fontSize: numeric(node.props[\"font-size\"], 10),\n fontFamily: own.fontFamily,\n fontWeight: node.props[\"font-weight\"] ? numeric(node.props[\"font-weight\"], 400) : undefined,\n fill: own.fill\n });\n }\n return null;\n }\n const children: Array<VNode | string> = [];\n for (const c of node.children) {\n if (typeof c === \"string\") {\n children.push(c);\n continue;\n }\n const kept = strip(c, own);\n if (kept) children.push(kept);\n }\n // Screen-only attributes are dropped here, so the markup handed to the\n // engine is exactly what it was before charts became interactive. A PDF has\n // nothing to hover.\n const props: VNode[\"props\"] = {};\n for (const [k, value] of Object.entries(node.props)) if (!SCREEN_ONLY.test(k)) props[k] = value;\n return { ...node, props, children };\n };\n\n const kept = strip(flat, {})!;\n return { markup: kept.children.map((c) => (typeof c === \"string\" ? c : toHtml(c))).join(\"\"), labels };\n}\n\n/* ------------------------------------------------------------------ */\n/* Parsing SVG that arrives as markup rather than as a VNode */\n/* ------------------------------------------------------------------ */\n\nconst ENTITIES: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \"\\u00a0\" };\n\nfunction decodeEntities(s: string): string {\n return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (whole, body: string) => {\n if (body.startsWith(\"#x\") || body.startsWith(\"#X\")) return String.fromCodePoint(Number.parseInt(body.slice(2), 16));\n if (body.startsWith(\"#\")) return String.fromCodePoint(Number.parseInt(body.slice(1), 10));\n return ENTITIES[body] ?? whole;\n });\n}\n\nconst TAG = /<\\s*(\\/)?\\s*([a-zA-Z][\\w:.-]*)((?:\\s+[\\w:.-]+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s\">]+))*)\\s*(\\/)?\\s*>/g;\nconst ATTR = /([\\w:.-]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\">]+))/g;\nconst SKIP = /<\\?[\\s\\S]*?\\?>|<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<![\\s\\S]*?>/g;\n\n/**\n * Parses a standalone SVG document into a VNode.\n *\n * Logos and other brand assets routinely arrive as an SVG data URI in an\n * `<img>`, which the engine cannot decode — it produces a grey box. Parsing\n * them here puts them through the same treatment as a chart, so their\n * transforms are flattened and their text is drawn.\n *\n * This handles the subset of XML that SVG assets use: elements, attributes,\n * text and entities. It is not a general XML parser and does not try to be.\n */\nexport function parseSvgMarkup(source: string): VNode | null {\n const text = source.replace(SKIP, \"\");\n const root: VNode = { tag: \"#root\", props: {}, children: [] };\n const stack: VNode[] = [root];\n let cursor = 0;\n\n TAG.lastIndex = 0;\n for (let m = TAG.exec(text); m; m = TAG.exec(text)) {\n const between = text.slice(cursor, m.index);\n if (between.trim()) stack[stack.length - 1]!.children.push(decodeEntities(between));\n cursor = TAG.lastIndex;\n\n const [, closing, tag, rawAttrs, selfClosing] = m;\n if (closing) {\n // Tolerate a stray close tag rather than unwinding past the root.\n if (stack.length > 1) stack.pop();\n continue;\n }\n\n const props: VProps = {};\n ATTR.lastIndex = 0;\n for (let a = ATTR.exec(rawAttrs ?? \"\"); a; a = ATTR.exec(rawAttrs ?? \"\")) {\n props[a[1]!] = decodeEntities(a[2] ?? a[3] ?? a[4] ?? \"\");\n }\n\n const node: VNode = { tag: tag!, props, children: [] };\n stack[stack.length - 1]!.children.push(node);\n if (!selfClosing) stack.push(node);\n }\n\n const svg = root.children.find((c): c is VNode => typeof c !== \"string\" && c.tag.toLowerCase() === \"svg\");\n return svg ?? null;\n}\n\n/** Decodes a `data:image/svg+xml` URI, whether percent-encoded or base64. */\nexport function svgFromDataUri(src: string): VNode | null {\n const match = /^data:image\\/svg\\+xml(;[^,]*)?,(.*)$/is.exec(src.trim());\n if (!match) return null;\n const isBase64 = (match[1] ?? \"\").toLowerCase().includes(\"base64\");\n try {\n const body = match[2] ?? \"\";\n // This runs in a browser as well as in Node, so decode without Buffer.\n const markup = isBase64 ? new TextDecoder().decode(Uint8Array.from(atob(body), (c) => c.charCodeAt(0))) : decodeURIComponent(body);\n return parseSvgMarkup(markup);\n } catch {\n return null;\n }\n}\n","/**\n * Drawing the evaluation mark with the engine's own primitives.\n *\n * Forme has a page-native watermark node, which is the right tool twice over:\n * it repeats on every page the engine emits without the caller counting them,\n * and it draws underneath the content rather than over it, so an evaluation\n * PDF reads exactly like a licensed one apart from the mark.\n *\n * The style is not optional. An unstyled watermark node draws solid black at\n * full opacity, which does make the point but also makes the document\n * unreadable — and an evaluation copy nobody can read is not an evaluation.\n */\nimport { mapStyle } from \"@formepdf/shared\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport type { FormeNode } from \"./vnode.js\";\nimport type { FormeStyle } from \"./style.js\";\n\nexport function watermarkNode(spec: WatermarkSpec): FormeNode {\n return {\n kind: { type: \"Watermark\", text: spec.text, font_size: spec.fontSize, angle: spec.angle },\n style: mapStyle({ color: spec.color, opacity: spec.opacity } as never) as FormeStyle,\n children: []\n };\n}\n","/**\n * Forme as a pure measurer.\n *\n * Forme is page-native: given a document it paginates and draws. But given a\n * page tall enough that nothing can overflow, it becomes a measurement engine —\n * it returns the laid-out tree with a box for every node, a `TextLine` per line\n * of wrapped text and a `TableRow` per row. That is exactly the geometry our own\n * paginator consumes, so BroadPaper keeps every pagination decision (keep\n * together, keep with next, orphans and widows, repeated table headers, page\n * breaks, splitting multi-column rows) while no browser is involved anywhere.\n *\n * Correlating engine output back to BroadPaper nodes is done structurally: the\n * translator records an annotation tree in lockstep with the nodes it emits, and\n * the layout tree comes back with the same shape (leaf `Text` nodes merely gain\n * `TextLine` children, which appends rather than reorders).\n */\nimport type { GeometryMap, NodeGeometry, ResolvedNode, SectionGeometry, TableRowGeometry } from \"@broadpaper/core\";\nimport type { FormeNode } from \"./vnode.js\";\n\n/** Mirrors an emitted node, carrying what we need to map geometry back. */\nexport interface Annotation {\n /** BroadPaper node key, when this node is a block wrapper. */\n key?: string;\n /** This node's subtree holds wrapped text whose line boxes we want. */\n text?: boolean;\n /** Row roles in emission order, for table nodes. */\n rowKinds?: Array<TableRowGeometry[\"kind\"]>;\n children: Annotation[];\n}\n\n/** A layout element as returned by Forme. */\nexport interface LayoutElement {\n x: number;\n y: number;\n width: number;\n height: number;\n nodeType: string;\n textContent?: string | null;\n children?: LayoutElement[];\n}\n\nexport interface LayoutPage {\n width: number;\n height: number;\n elements: LayoutElement[];\n}\n\n/** Height of the measurement page. Tall enough that nothing paginates. */\nexport const UNBOUNDED_PAGE_HEIGHT = 200_000;\n\nfunction descendants(el: LayoutElement, nodeType: string, out: LayoutElement[] = []): LayoutElement[] {\n for (const c of el.children ?? []) {\n if (c.nodeType === nodeType) out.push(c);\n descendants(c, nodeType, out);\n }\n return out;\n}\n\n/**\n * Walks the annotation tree and the layout tree together, recording a geometry\n * entry for every annotated node.\n */\nfunction collect(ann: Annotation, el: LayoutElement, origin: { x: number; y: number }, out: Record<string, NodeGeometry>): void {\n if (ann.key) {\n const g: NodeGeometry = {\n top: round(el.y - origin.y),\n height: round(el.height),\n // Both coordinates are relative to the section, which is what the\n // paginator hands back as a repeated header’s offset inside the page\n // content box. Leaving x absolute pushed every repeated table header one\n // page margin to the right and its last column off the page.\n left: round(el.x - origin.x),\n width: round(el.width)\n };\n if (ann.text) {\n const lines = descendants(el, \"TextLine\");\n if (lines.length) {\n // The paginator splits at the boundary *between* lines, so record the\n // midpoint of each gap; the last entry is the node's own bottom.\n const sorted = [...lines].sort((a, b) => a.y - b.y);\n const bounds: number[] = [];\n for (let i = 0; i < sorted.length - 1; i++) {\n const bottom = sorted[i]!.y + sorted[i]!.height;\n bounds.push(round((bottom + sorted[i + 1]!.y) / 2 - origin.y));\n }\n bounds.push(round(el.y + el.height - origin.y));\n g.lines = bounds;\n }\n }\n if (ann.rowKinds) {\n const rows = descendants(el, \"TableRow\").sort((a, b) => a.y - b.y);\n g.rows = rows.map((r, i) => ({ top: round(r.y - origin.y), height: round(r.height), kind: ann.rowKinds![i] ?? \"body\" }));\n }\n out[ann.key] = g;\n }\n const kids = el.children ?? [];\n for (let i = 0; i < ann.children.length; i++) {\n const childEl = kids[i];\n if (!childEl) continue;\n collect(ann.children[i]!, childEl, origin, out);\n }\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nexport interface MeasuredSection {\n section: ResolvedNode;\n node: FormeNode;\n ann: Annotation;\n}\n\n/**\n * Builds the geometry map our paginator expects from Forme's layout of an\n * unbounded page. `pageElements` are the top-level elements of that page, in the\n * same order as `sections`.\n */\nexport function geometryFromLayout(sections: MeasuredSection[], pageElements: LayoutElement[], width: number): GeometryMap {\n const out: GeometryMap = {};\n for (let i = 0; i < sections.length; i++) {\n const el = pageElements[i];\n const { section, ann } = sections[i]!;\n if (!el) {\n out[section.key] = { height: 0, width, nodes: {} };\n continue;\n }\n const nodes: Record<string, NodeGeometry> = {};\n collect(ann, el, { x: el.x, y: el.y }, nodes);\n const geom: SectionGeometry = { height: round(el.height), width, nodes };\n // The section itself is the origin, so it always starts at zero.\n nodes[section.key] = { top: 0, height: geom.height, left: 0, width: round(el.width) };\n out[section.key] = geom;\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ */\n/* Measurer */\n/* ------------------------------------------------------------------ */\n\nimport { renderNode, type BlockRegistry, type DocumentStyles, type FormatContext, type RenderMode, type RenderTreeOptions, type Theme } from \"@broadpaper/core\";\nimport { translate, type TranslateContext } from \"./vnode.js\";\nimport { pxToPt } from \"./style.js\";\n\nexport interface FormeRenderer {\n (doc: Record<string, unknown>): Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>;\n}\n\nexport interface FormeMeasurerOptions {\n registry: BlockRegistry;\n theme: Theme;\n styles: DocumentStyles;\n format: FormatContext;\n mode?: RenderMode;\n /** Page width in CSS pixels, used for the measurement page. */\n pageWidth: number;\n margins: { top: number; right: number; bottom: number; left: number };\n fonts?: unknown[];\n /** Injected so the caller picks the Forme entry point (node, browser, worker). */\n render: FormeRenderer;\n}\n\nfunction scale(el: LayoutElement, factor: number): LayoutElement {\n return {\n ...el,\n x: el.x * factor,\n y: el.y * factor,\n width: el.width * factor,\n height: el.height * factor,\n children: (el.children ?? []).map((c) => scale(c, factor))\n };\n}\n\n/**\n * Measures resolved sections with Forme, returning geometry in CSS pixels — the\n * same shape `DomMeasurer` produces, so the paginator and the editor cannot tell\n * which one measured.\n */\nexport class FormeMeasurer {\n readonly warnings = new Set<string>();\n\n constructor(private readonly opts: FormeMeasurerOptions) {}\n\n private renderOptions(): RenderTreeOptions {\n return {\n registry: this.opts.registry,\n theme: this.opts.theme,\n styles: this.opts.styles,\n mode: this.opts.mode ?? \"preview\",\n page: { number: 1, total: 1 },\n format: this.opts.format,\n width: this.contentWidth\n };\n }\n\n get contentWidth(): number {\n return Math.max(0, this.opts.pageWidth - this.opts.margins.left - this.opts.margins.right);\n }\n\n async measure(sections: ResolvedNode[], width = this.contentWidth): Promise<GeometryMap> {\n if (!sections.length) return {};\n const ctx: TranslateContext = { warnings: this.warnings, design: (this.opts.mode ?? \"preview\") === \"design\", suppressPageBreaks: true };\n const renderOpts = { ...this.renderOptions(), width };\n const measured: MeasuredSection[] = [];\n for (const section of sections) {\n const v = renderNode(section, renderOpts, width);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) measured.push({ section, node: t.node, ann: t.ann });\n }\n if (!measured.length) return {};\n\n const m = this.opts.margins;\n const doc: Record<string, unknown> = {\n children: [\n {\n kind: {\n type: \"Page\",\n config: {\n // Tall enough that nothing can paginate: this is a measuring page.\n size: { Custom: { width: pxToPt(this.opts.pageWidth), height: UNBOUNDED_PAGE_HEIGHT } },\n margin: { top: pxToPt(m.top), right: pxToPt(m.right), bottom: pxToPt(m.bottom), left: pxToPt(m.left) },\n wrap: true\n }\n },\n style: {},\n children: measured.map((x) => x.node)\n }\n ],\n metadata: {},\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: {}\n };\n if (this.opts.fonts?.length) doc.fonts = this.opts.fonts;\n\n const result = await this.opts.render(doc);\n const pages = ((result.layout as { pages?: LayoutPage[] } | null)?.pages ?? []) as LayoutPage[];\n // Points back to CSS pixels; BroadPaper works in pixels throughout.\n const toPx = 96 / 72;\n const elements = (pages[0]?.elements ?? []).map((e) => scale(e, toPx));\n for (const w of result.warnings ?? []) this.warnings.add(w);\n return geometryFromLayout(measured, elements, width);\n }\n}\n","/**\n * Forme as the editor's measurer.\n *\n * The canvas normally measures in the browser, which is immediate and free.\n * That is the right default, but it means the editor and the PDF are laid out\n * by two different engines, and where they disagree a page breaks in one place\n * on screen and another in the file. Measuring the canvas with the same engine\n * that renders the PDF removes the disagreement entirely: a break you see is a\n * break you get.\n *\n * The engine is injected rather than imported so this module stays neutral\n * about which Forme entry point the host uses — browser, worker or node.\n */\nimport type { GeometryMap, RenderTreeOptions, ResolvedNode, SectionGeometry } from \"@broadpaper/core\";\nimport { FormeMeasurer, type FormeRenderer } from \"./measure.js\";\n\nexport interface FormeEditorMeasurerOptions {\n /** The engine call, e.g. `renderSerializedDocWithLayout` from `@formepdf/core/browser`. */\n render: FormeRenderer;\n /** Font files the engine should use, matching the theme's families. */\n fonts?: unknown[];\n /** Called for every distinct translation warning, once. */\n onWarning?(message: string): void;\n}\n\n/** FNV-1a 32-bit. Fast, and collisions here only cost a re-measure. */\nfunction hash(s: string): string {\n let h = 0x811c9dc5;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(36) + s.length.toString(36);\n}\n\n/**\n * Measures resolved sections with Forme, caching by section content.\n *\n * Engine measurement is far slower than reading the DOM, so an edit must not\n * re-measure the whole document. Only sections whose content actually changed\n * are sent, and they go in one call rather than one call each.\n */\nexport class FormeEditorMeasurer {\n private opts: RenderTreeOptions | null = null;\n private readonly cache = new Map<string, SectionGeometry>();\n private readonly seen = new Set<string>();\n\n constructor(private readonly config: FormeEditorMeasurerOptions) {}\n\n setOptions(opts: RenderTreeOptions): void {\n this.opts = opts;\n }\n\n clearCache(): void {\n this.cache.clear();\n }\n\n destroy(): void {\n this.cache.clear();\n }\n\n private key(section: ResolvedNode, width: number, mode: string): string {\n return hash(JSON.stringify(section)) + \":\" + Math.round(width * 100) + \":\" + mode;\n }\n\n async measure(sections: ResolvedNode[], width: number): Promise<GeometryMap> {\n const opts = this.opts;\n if (!opts) throw new Error(\"FormeEditorMeasurer.setOptions() must be called before measure()\");\n\n const out: GeometryMap = {};\n const pending: ResolvedNode[] = [];\n const keys = new Map<string, string>();\n for (const section of sections) {\n const k = this.key(section, width, opts.mode);\n const hit = this.cache.get(k);\n if (hit) out[section.key] = hit;\n else {\n pending.push(section);\n keys.set(section.key, k);\n }\n }\n if (!pending.length) return out;\n\n // The measuring page is exactly the content box: giving it the width the\n // caller asked for, with no margins, keeps the two definitions of \"width\"\n // from ever drifting apart.\n const measurer = new FormeMeasurer({\n registry: opts.registry,\n theme: opts.theme,\n styles: opts.styles,\n format: opts.format,\n mode: opts.mode,\n pageWidth: width,\n margins: { top: 0, right: 0, bottom: 0, left: 0 },\n fonts: this.config.fonts,\n render: this.config.render\n });\n\n const measured = await measurer.measure(pending, width);\n for (const [sectionKey, geometry] of Object.entries(measured)) {\n out[sectionKey] = geometry;\n const k = keys.get(sectionKey);\n if (k) this.cache.set(k, geometry);\n }\n\n for (const w of measurer.warnings) {\n if (this.seen.has(w)) continue;\n this.seen.add(w);\n this.config.onWarning?.(w);\n }\n return out;\n }\n}\n","/**\n * @broadpaper/forme — browserless PDF output.\n *\n * The Chromium backend (`@broadpaper/pdf`) prints a document BroadPaper has\n * already paginated. This backend instead hands Forme the flowing content and\n * lets its page-native Rust/WASM engine paginate and draw: no browser, no\n * native dependencies, runs in Node, edge runtimes and the browser.\n *\n * The trade-off is explicit: pagination decisions move from BroadPaper's\n * paginator to Forme's, so the editor's on-screen page breaks are an\n * approximation of this output until the editor is switched to the same engine.\n * `renderPdf` returns Forme's own page geometry so callers can compare.\n */\nimport {\n computePageGeometry,\n mergeTheme,\n renderNode,\n resolveTemplate,\n migrateTemplate,\n type BlockRegistry,\n type DataSource,\n type RenderTreeOptions,\n type ReportData,\n type ReportTemplate,\n type AnyVersionTemplate,\n type ResolvedNode,\n type Theme\n} from \"@broadpaper/core\";\nimport { mapStyle } from \"@formepdf/shared\";\nimport { producerString, resolveLicenseStatus, watermarkFor, type LicenseStatus } from \"@broadpaper/license\";\nimport { vnodeToForme, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { pxToPt } from \"./style.js\";\n\nexport { vnodeToForme, translate } from \"./vnode.js\";\nexport { FormeMeasurer, geometryFromLayout, UNBOUNDED_PAGE_HEIGHT } from \"./measure.js\";\nexport type { FormeMeasurerOptions, FormeRenderer, Annotation, LayoutElement, LayoutPage } from \"./measure.js\";\nexport type { Translated, TranslateContext } from \"./vnode.js\";\nexport type { FormeNode } from \"./vnode.js\";\nexport { translateStyle, parseDeclarations, pxToPt, PX_TO_PT } from \"./style.js\";\nexport { watermarkNode } from \"./watermark.js\";\n\n/**\n * Licensing, re-exported so a host configures BroadPaper from whichever package\n * it already imports rather than adding one for a single call.\n *\n * BroadPaper.configure({ license: process.env.BROADPAPER_LICENSE });\n *\n * Without a licence every one of these functions still renders; the PDF simply\n * carries the evaluation mark. See `@broadpaper/license`.\n */\nexport { BroadPaper, configure, resolveLicenseStatus, verifyLicense, parseLicense } from \"@broadpaper/license\";\nexport type { BroadPaperConfig, Entitlement, LicensePayload, LicenseState, LicenseStatus } from \"@broadpaper/license\";\n\nexport interface FormeFont {\n family: string;\n /** TTF/OTF bytes, a data: URI, or a filesystem path (Node only). */\n src: string | Uint8Array;\n weight?: number;\n style?: \"normal\" | \"italic\";\n}\n\nexport interface RenderFormePdfOptions {\n template: ReportTemplate | AnyVersionTemplate;\n registry: BlockRegistry;\n data?: ReportData;\n theme?: Partial<Theme>;\n dataSources?: DataSource[];\n now?: Date;\n locale?: string;\n currency?: string;\n timeZone?: string;\n metadata?: { title?: string; author?: string; subject?: string; creator?: string; lang?: string };\n /** Fonts to embed. Without these Forme falls back to its standard faces. */\n fonts?: FormeFont[];\n /** Emit a tagged (accessible) PDF. */\n tagged?: boolean;\n /** PDF/UA-1 conformance. Requires an embeddable font. */\n pdfUa?: boolean;\n /** PDF/A conformance level. */\n pdfA?: \"2b\" | \"2u\" | \"2a\" | \"3b\" | \"3u\" | \"3a\";\n /**\n * A licence for this render only, overriding whatever `configure` was given.\n *\n * Almost nothing should need it: a process renders under one licence, and\n * setting it once at startup is both less code and impossible to forget on\n * one export path. It exists for a multi-tenant host that renders on behalf\n * of several licensed organisations from one process.\n */\n license?: string | null;\n /**\n * Injected renderer, so the caller controls which Forme entry point is used\n * (`@formepdf/core`, `/browser`, or `/worker`). Defaults to a dynamic import\n * of `@formepdf/core`.\n */\n renderer?: (doc: Record<string, unknown>) => Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>;\n}\n\nexport interface FormePageInfo {\n width: number;\n height: number;\n contentWidth: number;\n contentHeight: number;\n elements: unknown[];\n}\n\nexport interface RenderFormePdfResult {\n pdf: Uint8Array;\n pages: number;\n /** Forme's own layout geometry — the basis for driving an editor from this engine. */\n layout: { pages: FormePageInfo[] } | null;\n /** Everything BroadPaper could not translate, plus everything Forme flagged. */\n warnings: string[];\n durationMs: number;\n}\n\n/**\n * Builds the Forme document JSON for a resolved BroadPaper document.\n *\n * Asynchronous only because it checks the licence, which it does itself rather\n * than taking a \"watermark this\" flag from its caller. Every route to a\n * BroadPaper PDF through this engine passes through here or through\n * `emitPages`, and a document built without the evaluation mark is a clean\n * unlicensed PDF — so the decision is made where the document is assembled and\n * nowhere else.\n */\nexport async function buildFormeDocument(opts: Omit<RenderFormePdfOptions, \"renderer\">): Promise<{ doc: Record<string, unknown>; warnings: string[]; license: LicenseStatus }> {\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const { template } = migrateTemplate(opts.template as AnyVersionTemplate);\n const theme = mergeTheme(opts.theme);\n const geom = computePageGeometry(template.page);\n const now = opts.now ?? new Date();\n const format = {\n locale: opts.locale ?? template.settings?.locale ?? \"en-GB\",\n currency: opts.currency ?? template.settings?.currency ?? \"GBP\",\n timeZone: opts.timeZone ?? template.settings?.timeZone,\n now\n };\n\n const resolved = resolveTemplate({\n template,\n registry: opts.registry,\n theme,\n dataSources: opts.dataSources,\n data: opts.data,\n mode: \"preview\",\n now,\n locale: format.locale,\n currency: format.currency,\n timeZone: format.timeZone\n });\n\n const renderOpts: RenderTreeOptions = {\n registry: opts.registry,\n theme,\n styles: template.styles,\n mode: \"preview\",\n page: { number: 1, total: 1 },\n format,\n width: geom.contentWidth\n };\n\n const ctx: TranslateContext = { warnings: new Set() };\n const translate = (sections: ResolvedNode[]): FormeNode[] => {\n const out: FormeNode[] = [];\n for (const s of sections) {\n const v = renderNode(s, renderOpts, geom.contentWidth);\n if (!v) continue;\n const node = vnodeToForme(v, ctx);\n if (node) out.push(node);\n }\n return out;\n };\n\n const children: FormeNode[] = [];\n // First child, so the mark sits under the report rather than over it. The\n // engine repeats a watermark node on every page it emits, which is what this\n // path needs: pagination here belongs to Forme, so BroadPaper does not know\n // how many pages there will be.\n const mark = watermarkFor(license);\n if (mark) children.push(watermarkNode(mark));\n // Running header/footer become Fixed regions, so page numbers and brand\n // details repeat without BroadPaper composing each page itself.\n const header = translate(resolved.header.default);\n if (header.length) children.push({ kind: { type: \"Fixed\", position: \"Header\" }, style: {}, children: header });\n const footer = translate(resolved.footer.default);\n if (footer.length) children.push({ kind: { type: \"Fixed\", position: \"Footer\" }, style: {}, children: footer });\n children.push(...translate(resolved.body));\n\n const page = {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(geom.width), height: pxToPt(geom.height) } },\n margin: { top: pxToPt(geom.margins.top), right: pxToPt(geom.margins.right), bottom: pxToPt(geom.margins.bottom), left: pxToPt(geom.margins.left) },\n wrap: true\n }\n },\n style: {},\n children\n };\n\n const doc: Record<string, unknown> = {\n children: [page],\n metadata: { title: template.name, creator: producerString(license), ...(opts.metadata ?? {}) },\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: mapStyle({ fontSize: pxToPt(theme.typography.baseFontSize ?? 11), fontFamily: theme.typography.bodyFont.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\") } as never)\n };\n if (opts.fonts?.length) doc.fonts = opts.fonts.map((f) => ({ family: f.family, src: f.src, weight: f.weight ?? 400, style: f.style ?? \"normal\" }));\n if (opts.tagged) doc.tagged = true;\n if (opts.pdfUa) doc.pdfUa = true;\n if (opts.pdfA) doc.pdfa = opts.pdfA;\n\n const warnings = [...ctx.warnings, ...resolved.warnings.map((w) => w.message)];\n return { doc, warnings, license };\n}\n\n/**\n * How this package reaches the engine when the caller injects no `renderer`.\n *\n * It is set by the entry point rather than imported here, because the two\n * runtimes need different Forme builds and a browser bundler must never even\n * see the other one. `@formepdf/core`'s default browser build is the\n * wasm-pack *bundler* target, whose `import * as wasm from \"./forme_bg.wasm\"`\n * Angular's builder rejects outright (\"WASM/ES module integration imports are\n * not supported with Zone.js applications\") — so a single bare import here\n * obliged every Angular host to go zoneless to use us at all. That is a\n * decision about the host's change detection, and a reporting SDK has no\n * business making it.\n *\n * `src/index.ts` installs the Node loader, `src/index.browser.ts` the browser\n * one, and the `browser` condition in this package's exports picks between\n * them. Neither bundle contains the other's import.\n */\nexport type EngineLoader = () => Promise<(doc: Record<string, unknown>) => Promise<{ pdf: Uint8Array; layout?: unknown; warnings?: string[] }>>;\n\nlet engineLoader: EngineLoader | null = null;\nlet engine: Awaited<ReturnType<EngineLoader>> | null = null;\n\n/**\n * Installs the engine used when no `renderer` is passed. Each entry point calls\n * this for its own runtime, which is all most hosts need; it is exported\n * because a host that reaches Forme some third way — a shared worker, a\n * pre-instantiated module, a pooled engine — has somewhere to say so once\n * rather than on every call.\n */\nexport function setEngineLoader(loader: EngineLoader): void {\n engineLoader = loader;\n}\n\nasync function defaultRenderer(doc: Record<string, unknown>) {\n if (!engineLoader) {\n throw new Error(\n \"No Forme engine is available. Import @broadpaper/forme from its package entry point, or pass a `renderer` to render with an engine you loaded yourself.\"\n );\n }\n // Cached: loading the engine means instantiating a WASM module, which is\n // expensive enough that doing it per render would dominate the render.\n engine ??= await engineLoader();\n return engine(doc);\n}\n\n/** Renders a BroadPaper template to PDF with no browser involved. */\nexport async function renderPdf(opts: RenderFormePdfOptions): Promise<RenderFormePdfResult> {\n const started = Date.now();\n const { doc, warnings } = await buildFormeDocument(opts);\n const render = opts.renderer ?? defaultRenderer;\n const result = await render(doc);\n const layout = (result.layout ?? null) as { pages: FormePageInfo[] } | null;\n return {\n pdf: result.pdf,\n pages: layout?.pages.length ?? 0,\n layout,\n warnings: [...warnings, ...(result.warnings ?? [])],\n durationMs: Date.now() - started\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* BroadPaper-paginated path */\n/* ------------------------------------------------------------------ */\n\nimport { computePageGeometry as pageGeometry, paginate, resolveValue, type GeometryMap, type PagedDocument } from \"@broadpaper/core\";\nimport { translate } from \"./vnode.js\";\nimport { geometryFromLayout, UNBOUNDED_PAGE_HEIGHT, type LayoutPage, type MeasuredSection } from \"./measure.js\";\nimport { emitPages } from \"./paged.js\";\n\nexport interface RenderPaginatedResult extends RenderFormePdfResult {\n /** The pages BroadPaper's own paginator decided. */\n paged: PagedDocument;\n /** Geometry measured by the engine, keyed by section. */\n geometry: GeometryMap;\n}\n\n/**\n * Renders with **BroadPaper owning pagination** and Forme acting only as a\n * measurer and a draw target — no browser, and every page-break rule\n * (keep together, keep with next, orphans and widows, repeated table headers,\n * explicit breaks, splitting multi-column rows) still comes from our paginator.\n *\n * Two passes through the engine: one onto a page tall enough that nothing can\n * overflow, which yields a box for every node, line and table row; then one that\n * draws the pages our paginator produced. Both passes lay text out with the same\n * engine at the same width, so the second cannot re-break what the first\n * measured.\n */\nexport async function renderPdfPaginated(opts: RenderFormePdfOptions): Promise<RenderPaginatedResult> {\n const started = Date.now();\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const { template } = migrateTemplate(opts.template as AnyVersionTemplate);\n const theme = mergeTheme(opts.theme);\n const geom = pageGeometry(template.page);\n const now = opts.now ?? new Date();\n const format = {\n locale: opts.locale ?? template.settings?.locale ?? \"en-GB\",\n currency: opts.currency ?? template.settings?.currency ?? \"GBP\",\n timeZone: opts.timeZone ?? template.settings?.timeZone,\n now\n };\n\n const resolved = resolveTemplate({\n template,\n registry: opts.registry,\n theme,\n dataSources: opts.dataSources,\n data: opts.data,\n mode: \"preview\",\n now,\n locale: format.locale,\n currency: format.currency,\n timeZone: format.timeZone\n });\n\n const renderOpts: RenderTreeOptions = {\n registry: opts.registry,\n theme,\n styles: template.styles,\n mode: \"preview\",\n page: { number: 1, total: 1 },\n format,\n width: geom.contentWidth\n };\n\n // We decided the pages; a break node here would let the engine add its own.\n const ctx: TranslateContext = { warnings: new Set(), suppressPageBreaks: true };\n const render = opts.renderer ?? defaultRenderer;\n\n /** Lays sections out on one unbounded page and reads their geometry back. */\n const measure = async (sections: ResolvedNode[]): Promise<GeometryMap> => {\n if (!sections.length) return {};\n const measured: MeasuredSection[] = [];\n for (const section of sections) {\n const v = renderNode(section, renderOpts, geom.contentWidth);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) measured.push({ section, node: t.node, ann: t.ann });\n }\n if (!measured.length) return {};\n const doc: Record<string, unknown> = {\n children: [\n {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(geom.width), height: UNBOUNDED_PAGE_HEIGHT } },\n margin: { top: pxToPt(geom.margins.top), right: pxToPt(geom.margins.right), bottom: pxToPt(geom.margins.bottom), left: pxToPt(geom.margins.left) },\n wrap: true\n }\n },\n style: {},\n children: measured.map((m) => m.node)\n }\n ],\n metadata: {},\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: baseStyle(theme)\n };\n if (opts.fonts?.length) doc.fonts = fontEntries(opts.fonts);\n const result = await render(doc);\n const pages = ((result.layout as { pages?: LayoutPage[] } | null)?.pages ?? []) as LayoutPage[];\n // Points back to CSS pixels: our paginator works in px throughout.\n const scale = 1 / PX_TO_PT_LOCAL;\n const scaled = pages[0]?.elements.map((e) => scaleElement(e, scale)) ?? [];\n return geometryFromLayout(measured, scaled, geom.contentWidth);\n };\n\n const geometry = await measure(resolved.body);\n const regionGeometry = await measure([...resolved.header.default, ...(resolved.header.firstPage ?? []), ...resolved.footer.default, ...(resolved.footer.firstPage ?? [])]);\n const paged = paginate({ document: resolved, geometry, page: geom, minPages: 1, regionGeometry });\n\n const pages = emitPages({\n resolved,\n paged,\n page: geom,\n renderOpts,\n ctx,\n geometry,\n background: template.page.background ? resolveValue(template.page.background, theme, \"#ffffff\") : undefined,\n watermark: watermarkFor(license)\n });\n const doc: Record<string, unknown> = {\n children: pages,\n metadata: { title: template.name, creator: producerString(license), ...(opts.metadata ?? {}) },\n defaultPage: { size: \"A4\", margin: { top: 54, right: 54, bottom: 54, left: 54 }, wrap: true },\n defaultStyle: baseStyle(theme)\n };\n if (opts.fonts?.length) doc.fonts = fontEntries(opts.fonts);\n if (opts.tagged) doc.tagged = true;\n if (opts.pdfUa) doc.pdfUa = true;\n if (opts.pdfA) doc.pdfa = opts.pdfA;\n\n const result = await render(doc);\n const layout = (result.layout ?? null) as { pages: FormePageInfo[] } | null;\n return {\n pdf: result.pdf,\n pages: layout?.pages.length ?? paged.totalPages,\n layout,\n paged,\n geometry,\n warnings: [\n ...ctx.warnings,\n ...resolved.warnings.map((w) => w.message),\n ...paged.warnings.map((w) => w.message),\n ...(result.warnings ?? [])\n ],\n durationMs: Date.now() - started\n };\n}\n\nconst PX_TO_PT_LOCAL = 72 / 96;\n\nfunction scaleElement(el: LayoutElementLike, scale: number): LayoutElementLike {\n return {\n ...el,\n x: el.x * scale,\n y: el.y * scale,\n width: el.width * scale,\n height: el.height * scale,\n children: (el.children ?? []).map((c) => scaleElement(c, scale))\n };\n}\n\ninterface LayoutElementLike {\n x: number;\n y: number;\n width: number;\n height: number;\n nodeType: string;\n textContent?: string | null;\n children?: LayoutElementLike[];\n}\n\nfunction baseStyle(theme: Theme): unknown {\n return mapStyle({\n fontSize: pxToPt(theme.typography.baseFontSize ?? 11),\n fontFamily: theme.typography.bodyFont.split(\",\")[0]!.trim().replace(/^['\"]|['\"]$/g, \"\")\n } as never);\n}\n\nfunction fontEntries(fonts: FormeFont[]): unknown[] {\n return fonts.map((f) => ({ family: f.family, src: f.src, weight: f.weight ?? 400, style: f.style ?? \"normal\" }));\n}\n\nexport { FormeEditorMeasurer, type FormeEditorMeasurerOptions } from \"./editor.js\";\n","/**\n * Pass 2: draw a document BroadPaper has already paginated.\n *\n * One Forme `Page` per page our paginator decided. Each page places absolutely\n * positioned windows onto the section render — the same model the Chromium\n * backend uses, so the engine makes no layout decisions of its own and every\n * keep-together, orphan/widow and repeated-header choice remains ours.\n *\n * The section is *cropped* to the window before it is drawn, not merely clipped\n * to it: see `clip.ts` for why a clip alone leaves every neighbouring page's\n * text in this page's content stream. The clip stays as well, for the nodes a\n * page genuinely cuts in half.\n */\nimport {\n renderNode,\n walkVNodes,\n type GeometryMap,\n type PagedDocument,\n type PageGeometry,\n type RenderTreeOptions,\n type ResolvedDocument,\n type ResolvedNode,\n type VNode\n} from \"@broadpaper/core\";\nimport { mapStyle } from \"@formepdf/shared\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport { cropToWindow } from \"./clip.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { translate, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { pxToPt, type FormeStyle } from \"./style.js\";\n\n/**\n * An absolutely positioned, optionally clipping box, in CSS pixels.\n *\n * `bleed` widens the box to the right without moving anything inside it. The\n * clip's job is vertical — it is the window onto the page — and clipping\n * horizontally at the content edge only ever cuts a word in half. The engine\n * occasionally sets a line a point or two wider than the box it was given\n * (most often when the theme names a font it does not have and it falls back),\n * and a word spilling a little into the margin reads as a tight line, whereas\n * the same word sliced down the middle reads as a broken renderer.\n */\nfunction box(left: number, top: number, width: number, height: number, children: FormeNode[], clip = true, bleed = 0): FormeNode {\n const style = mapStyle({\n position: \"absolute\",\n left: pxToPt(left),\n top: pxToPt(top),\n width: pxToPt(width + bleed),\n height: pxToPt(height),\n ...(clip ? { overflow: \"hidden\" } : {})\n } as never) as FormeStyle;\n return { kind: { type: \"View\" }, style, children };\n}\n\n/** Strips a rendered table down to its header rows, for repeating across pages. */\nfunction headerOnly(v: VNode): VNode {\n const clone: VNode = structuredClone(v);\n walkVNodes(clone, (n) => {\n if (n.tag === \"table\") {\n n.children = n.children.filter((c) => typeof c !== \"string\" && (c.tag === \"colgroup\" || c.tag === \"thead\"));\n return false;\n }\n return true;\n });\n return clone;\n}\n\nexport interface PagedEmitInput {\n resolved: ResolvedDocument;\n paged: PagedDocument;\n page: PageGeometry;\n renderOpts: RenderTreeOptions;\n ctx: TranslateContext;\n /** The geometry the paginator broke pages with. Drives cropping too, so the\n * two can never disagree about where a page's window falls. */\n geometry: GeometryMap;\n /** Page background, already resolved to a concrete colour. */\n background?: string;\n /**\n * The evaluation mark, or null when the licence says the output is clean.\n * One node per page: this path emits its own pages, so the engine's habit of\n * repeating a watermark across the pages it paginated does not apply.\n */\n watermark?: WatermarkSpec | null;\n}\n\nfunction sectionsByKey(doc: ResolvedDocument): Map<string, ResolvedNode> {\n const map = new Map<string, ResolvedNode>();\n const visit = (n: ResolvedNode) => {\n map.set(n.key, n);\n n.children.forEach(visit);\n };\n for (const list of [doc.body, doc.header.default, doc.header.firstPage ?? [], doc.footer.default, doc.footer.firstPage ?? []]) list.forEach(visit);\n return map;\n}\n\nfunction isPageDependent(nodes: ResolvedNode[]): boolean {\n const check = (n: ResolvedNode): boolean => n.pageDependent === true || n.children.some(check);\n return nodes.some(check);\n}\n\n/** Emits the Forme `Page` nodes for an already-paginated document. */\nexport function emitPages(input: PagedEmitInput): FormeNode[] {\n const { resolved, paged, page, renderOpts, ctx, geometry } = input;\n const byKey = sectionsByKey(resolved);\n const width = page.contentWidth;\n\n // Body content is normally page-independent, so a section rendered for one\n // window can be reused for an identical window on another page; only\n // re-render when a block reads `page.*`.\n // How far content may spill past the content box before the page cuts it:\n // as far as the right margin, and no further.\n const bleed = page.margins.right;\n const bodyDependsOnPage = isPageDependent(resolved.body);\n const cache = new Map<string, { node: FormeNode; offset: number }>();\n const translateSection = (section: ResolvedNode, opts: RenderTreeOptions, from: number, to: number): { node: FormeNode; offset: number } | null => {\n const cacheKey = `${section.key}|${from}|${to}`;\n if (!bodyDependsOnPage && cache.has(cacheKey)) return cache.get(cacheKey)!;\n const v = renderNode(section, opts, width);\n if (!v) return null;\n const geom = geometry[section.key];\n const cropped = geom ? cropToWindow(v, geom, from, to) : { node: v, offset: 0 };\n const t = translate(cropped.node, ctx);\n if (!t) return null;\n const out = { node: t.node, offset: cropped.offset };\n if (!bodyDependsOnPage) cache.set(cacheKey, out);\n return out;\n };\n\n const region = (sections: ResolvedNode[], opts: RenderTreeOptions): FormeNode[] => {\n const out: FormeNode[] = [];\n for (const s of sections) {\n const v = renderNode(s, opts, width);\n if (!v) continue;\n const t = translate(v, ctx);\n if (t) out.push(t.node);\n }\n return out;\n };\n\n return paged.pages.map((p) => {\n const opts: RenderTreeOptions = { ...renderOpts, page: { number: p.number, total: paged.totalPages } };\n const children: FormeNode[] = [];\n // Before the content, so the mark is under the report and not across it.\n if (input.watermark) children.push(watermarkNode(input.watermark));\n\n const headerSections = p.first && resolved.header.firstPage ? resolved.header.firstPage : resolved.header.default;\n if (headerSections.length && page.headerHeight > 0) {\n children.push(box(page.margins.left, page.headerTop, width, page.headerHeight, region(headerSections, opts)));\n }\n\n const fragments: FormeNode[] = [];\n for (const f of p.fragments) {\n const section = byKey.get(f.sectionKey);\n if (!section) continue;\n const extra = f.repeatHeaders.reduce((a, r) => a + r.height, 0);\n const inner: FormeNode[] = [];\n\n for (const r of f.repeatHeaders) {\n const table = byKey.get(r.tableKey);\n if (!table) continue;\n const v = renderNode(table, opts, r.width);\n if (!v) continue;\n const t = translate(headerOnly(v), ctx);\n if (t) inner.push(box(r.left, 0, r.width, r.height, [t.node]));\n }\n\n const content = translateSection(section, opts, f.from, f.to);\n if (content) {\n // The window shows [from, to) of the section, so the content is shifted\n // up by `from` to bring that slice into the box. Cropping a cut table\n // to its visible rows makes everything from the table onward sit\n // `offset` higher than the geometry says, so the shift gives that back.\n // Everything else outside the window has been cropped away, and only\n // nodes the window genuinely cuts still rely on the clip.\n const shifted: FormeNode = {\n kind: { type: \"View\" },\n style: mapStyle({ position: \"absolute\", left: 0, top: pxToPt(content.offset - f.from), width: pxToPt(width) } as never) as FormeStyle,\n children: [content.node]\n };\n inner.push(box(0, extra, width, f.to - f.from, [shifted], true, bleed));\n }\n fragments.push(box(0, f.y, width, f.height, inner, true, bleed));\n }\n children.push(box(page.margins.left, page.contentTop, width, page.contentHeight, fragments, true, bleed));\n\n const footerSections = p.first && resolved.footer.firstPage ? resolved.footer.firstPage : resolved.footer.default;\n if (footerSections.length && page.footerHeight > 0) {\n children.push(box(page.margins.left, page.footerTop, width, page.footerHeight, region(footerSections, opts)));\n }\n\n return {\n kind: {\n type: \"Page\",\n config: {\n size: { Custom: { width: pxToPt(page.width), height: pxToPt(page.height) } },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n // Nothing may reflow: this page is exactly what the paginator decided.\n wrap: false\n }\n },\n style: input.background ? (mapStyle({ backgroundColor: input.background } as never) as FormeStyle) : {},\n children\n };\n });\n}\n","/**\n * Cropping a section's render down to the window a single page shows.\n *\n * A page draws its share of a section by shifting the whole section up and\n * clipping. Clipping is a graphics-state operation: it hides ink, but the text\n * is still in that page's content stream. Extractors that do not model clip\n * paths — pdf.js and Poppler, which is most of the ecosystem — therefore report\n * a page's text as including its neighbours', so copying a page out of the PDF\n * yields text the reader cannot see, and a screen reader reads a page three\n * times over. It also means every page carries the whole document's ink at\n * coordinates far outside the media box, which is exactly the construct\n * renderers disagree about.\n *\n * There is a second, louder reason. The engine will not lay anything out taller\n * than the page it is drawn on: a table, a text block or a plain box that\n * overflows is truncated, whatever box it sits in and whatever the overflow\n * says. Handing it a hundred-row table and asking for rows 40-80 drew the first\n * ten and dropped the rest. Nothing this module produces may be taller than a\n * page.\n *\n * So content is cropped before it is drawn:\n *\n * - A node wholly outside the window becomes an empty box of exactly the height\n * it measured, which leaves the layout the paginator decided untouched.\n * - A table the window cuts keeps only the rows the window shows. That makes\n * the table shorter than it was, so everything from the table onward moves up\n * by however much was dropped above the window — one number, reported back as\n * `offset` so the page can take it off the shift it was going to apply.\n *\n * Cropping is driven by the same geometry the paginator broke pages with, so\n * the two can never disagree about where a page's window falls.\n */\nimport type { SectionGeometry, TableRowGeometry, VNode } from \"@broadpaper/core\";\nimport { styleString } from \"@broadpaper/core\";\n\nconst EPS = 0.01;\n\ninterface Window {\n geom: SectionGeometry;\n from: number;\n to: number;\n /** Height removed from above the window, which the caller must compensate. */\n dropped: number;\n}\n\nexport interface Cropped {\n node: VNode;\n /**\n * How much shorter the content above the window is now. Everything from that\n * point on sits this many pixels higher than the geometry says, so a page\n * drawing this must shift by `from - offset` rather than by `from`.\n */\n offset: number;\n}\n\n/** Returns `root` cropped to `[from, to)`. The input is not mutated. */\nexport function cropToWindow(root: VNode, geom: SectionGeometry, from: number, to: number): Cropped {\n const w: Window = { geom, from, to, dropped: 0 };\n const node = crop(root, w, undefined);\n return { node, offset: w.dropped };\n}\n\nfunction outside(w: Window, top: number, height: number): boolean {\n return top + height <= w.from + EPS || top >= w.to - EPS;\n}\n\nfunction crop(v: VNode, w: Window, rows: TableRowGeometry[] | undefined): VNode {\n const key = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : undefined;\n const g = key ? w.geom.nodes[key] : undefined;\n if (g) {\n if (outside(w, g.top, g.height)) return blank(v, g.height);\n // A block that measured table rows carries them on its own wrapper, so the\n // rows travel down to whichever descendant is the actual `<table>`.\n if (g.rows) rows = g.rows;\n }\n\n if (v.tag === \"table\" && rows) return cropTable(v, w, rows);\n\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = crop(c, w, rows);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n}\n\n/**\n * Replaces a node with an empty box the same height, keeping the margins that\n * decide where its siblings sit.\n */\nfunction blank(v: VNode, height: number): VNode {\n const kept = styleString(v.props.style)\n .split(\";\")\n .map((d) => d.trim())\n .filter((d) => d && !/^height\\s*:/i.test(d));\n kept.push(`height:${round(height)}px`);\n return { ...v, props: { ...v.props, style: kept.join(\";\") }, children: [] };\n}\n\n/**\n * Keeps only the rows the window shows.\n *\n * Row geometry is recorded in emission order and the translator walks\n * `thead`/`tbody`/`tfoot` in document order, so the two line up by index.\n * Dropping rows rather than blanking them is what keeps the table inside a\n * page's worth of height; the rows dropped from above the window are added to\n * `w.dropped`, because everything below them — including whatever follows the\n * table on this page — has moved up by exactly that much.\n *\n * At most one table per fragment can be cut: a window is contiguous, so any\n * other table in the section is wholly inside it or wholly outside it, and a\n * wholly-outside one has already been blanked by its block wrapper.\n */\nfunction cropTable(table: VNode, w: Window, rows: TableRowGeometry[]): VNode {\n if (rows.length === 0) return table;\n const keep = rows.map((r) => !outside(w, r.top, r.height));\n if (keep.every(Boolean)) return table;\n\n const first = keep.indexOf(true);\n // Nothing of this table is on this page: an empty table draws nothing, and\n // whatever follows it is off the window too.\n if (first === -1) return { tag: \"div\", props: { style: \"height:0\" }, children: [] };\n w.dropped += rows[first]!.top - rows[0]!.top;\n\n let index = 0;\n const rewrite = (node: VNode): VNode | null => {\n const children: Array<VNode | string> = [];\n for (const c of node.children) {\n if (typeof c === \"string\") continue;\n if (c.tag === \"thead\" || c.tag === \"tbody\" || c.tag === \"tfoot\") {\n const next = rewrite(c);\n if (next) children.push(next);\n } else if (c.tag === \"tr\") {\n if (keep[index++]) children.push(c);\n } else children.push(c);\n }\n // A `tbody` left with no rows would still be emitted; drop it. The table\n // itself is kept even when empty, so its column widths survive.\n if (node !== table && !children.some((c) => typeof c !== \"string\" && c.tag === \"tr\")) return null;\n return { ...node, children };\n };\n\n return rewrite(table)!;\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n"],"mappings":"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","names":["kept","box","blank","mapStyle","round","renderNode","mapStyle","resolveLicenseStatus","renderNode","walkVNodes","mapStyle","styleString","round","mapStyle","walkVNodes","renderNode","translate","renderNode","mapStyle","doc","result","pages","scale"]}
|