@broadpaper/forme 0.4.0 → 0.4.1

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.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Browserless PDF generation for BroadPaper, via the Forme WebAssembly engine. The recommended backend.
8
8
 
9
- Part of [**BroadPaper**](https://www.broadpaper.com/developers/) — an embeddable visual report designer and PDF renderer.
9
+ Part of [**BroadPaper**](https://www.broadpaper.com/developers/?utm_source=npm&utm_medium=readme) — an embeddable visual report designer and PDF renderer.
10
10
  Your users design the report in your application; BroadPaper owns the layout, the branding,
11
11
  the pagination and the output.
12
12
 
@@ -43,7 +43,7 @@ production use. No seats, no activation, no machine binding, no telemetry, and n
43
43
  any point.
44
44
 
45
45
  - [How licensing works](https://www.broadpaper.com/docs/guide/licensing/)
46
- - [Pricing](https://www.broadpaper.com/developers/pricing/)
46
+ - [Pricing](https://www.broadpaper.com/developers/pricing/?utm_source=npm&utm_medium=readme)
47
47
  - [Licence agreement](https://www.broadpaper.com/legal/terms/)
48
48
 
49
49
  ## Documentation
@@ -51,6 +51,8 @@ any point.
51
51
  - [Browserless PDF](https://www.broadpaper.com/docs/guide/browserless-pdf)
52
52
  - [Themes and branding](https://www.broadpaper.com/docs/guide/themes)
53
53
  - [Full documentation](https://www.broadpaper.com/docs/)
54
+ - [Sample application](https://github.com/codingbadger/broadpaper-sample-application): the same app in React and Angular over one .NET back end
55
+ - [How BroadPaper compares](https://www.broadpaper.com/developers/compare/?utm_source=npm&utm_medium=readme) with react-pdf, pdfmake, Puppeteer and embedded report designers
54
56
 
55
57
  ## Support
56
58
 
@@ -38,6 +38,21 @@ function num(value) {
38
38
  const n = Number.parseFloat(value);
39
39
  return Number.isFinite(n) ? n : void 0;
40
40
  }
41
+ function flexShorthand(value) {
42
+ const v = value.trim().toLowerCase();
43
+ if (v === "none") return { grow: 0, shrink: 0 };
44
+ if (v === "auto") return { grow: 1, shrink: 1 };
45
+ if (v === "initial") return { grow: 0, shrink: 1 };
46
+ const parts = v.split(/\s+/).filter(Boolean);
47
+ const isCount = (p) => /^-?(\d+\.?\d*|\.\d+)$/.test(p);
48
+ const [a, b, c] = parts;
49
+ if (!a) return {};
50
+ if (parts.length === 1) return isCount(a) ? { grow: num(a), shrink: 1, basis: 0 } : { grow: 1, shrink: 1, basis: length(a) };
51
+ if (parts.length === 2) {
52
+ return isCount(b) ? { grow: num(a), shrink: num(b), basis: 0 } : { grow: num(a), shrink: 1, basis: length(b) };
53
+ }
54
+ return { grow: num(a), shrink: num(b), basis: length(c) };
55
+ }
41
56
  function colour(value) {
42
57
  const v = value.trim().toLowerCase();
43
58
  if (!v || v === "transparent" || v === "none" || v === "inherit" || v === "currentcolor") return void 0;
@@ -127,9 +142,13 @@ function translateStyle(css) {
127
142
  case "flex-wrap":
128
143
  set("flexWrap", value === "wrap" ? "wrap" : "nowrap");
129
144
  break;
130
- case "flex":
131
- set("flexGrow", num(value.split(/\s+/)[0] ?? "0"));
145
+ case "flex": {
146
+ const f = flexShorthand(value);
147
+ set("flexGrow", f.grow);
148
+ set("flexShrink", f.shrink);
149
+ set("flexBasis", f.basis);
132
150
  break;
151
+ }
133
152
  case "flex-grow":
134
153
  set("flexGrow", num(value));
135
154
  break;
@@ -701,7 +720,7 @@ function translate(v, ctx) {
701
720
  if (textual && (!blank2 || /bp-p--empty/.test(cls))) {
702
721
  const kind = heading ? { type: "Heading", level: Number(heading[1]), content } : { type: "Text", content };
703
722
  const node = { kind, style, children: [] };
704
- if (v.tag === "a" && typeof v.props.href === "string") node.href = v.props.href;
723
+ if (v.tag === "a" && typeof v.props.href === "string") kind.href = v.props.href;
705
724
  result = leaf(node);
706
725
  } else {
707
726
  const inner = childNodes(v, ctx);
@@ -1147,8 +1166,11 @@ function creditNode(spec, width, ctx) {
1147
1166
  });
1148
1167
  }
1149
1168
  children.push({
1150
- tag: "span",
1151
- props: { style: { "font-size": `${size}px`, color: spec.color, opacity: String(spec.opacity), "line-height": "1.2" } },
1169
+ tag: spec.href ? "a" : "span",
1170
+ props: {
1171
+ ...spec.href ? { href: spec.href } : {},
1172
+ style: { "font-size": `${size}px`, color: spec.color, opacity: String(spec.opacity), "line-height": "1.2" }
1173
+ },
1152
1174
  children: [spec.text]
1153
1175
  });
1154
1176
  const line = {
@@ -1878,4 +1900,4 @@ export {
1878
1900
  verifyLicense,
1879
1901
  parseLicense
1880
1902
  };
1881
- //# sourceMappingURL=chunk-QA4APTWM.js.map
1903
+ //# sourceMappingURL=chunk-FAKBQDQG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/style.ts","../src/vnode.ts","../src/svg.ts","../src/watermark.ts","../src/measure.ts","../src/fonts.ts","../src/editor.ts","../src/api.ts","../src/credit.ts","../src/long-tables.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/**\n * The `flex` shorthand, expanded — all three terms, not just the grow one.\n *\n * Reading only the first term is how `flex: 0 0 40%` became \"do not grow\" with\n * no basis at all, so a key/value list's label sized itself to its own text\n * instead of taking 40% of the row. That left the value beside it wider in the\n * file than in the browser, and a line that wrapped on the canvas fitted on one\n * line in the PDF: a section measured a line shorter than it draws, which\n * preview then crops. A field added to a section was enough to lose its last\n * row, and the section tolerance in `measure-parity.test.ts` was wide enough to\n * let a sixteen-point disagreement sit there unnoticed.\n *\n * The omitted-term defaults are CSS's own: a bare number is `<n> 1 0%`, a bare\n * basis is `1 1 <basis>`. `auto`, `none` and `initial` leave the basis unset,\n * which is the engine's automatic sizing and what those keywords mean.\n */\nfunction flexShorthand(value: string): { grow?: number; shrink?: number; basis?: number | string } {\n const v = value.trim().toLowerCase();\n if (v === \"none\") return { grow: 0, shrink: 0 };\n if (v === \"auto\") return { grow: 1, shrink: 1 };\n if (v === \"initial\") return { grow: 0, shrink: 1 };\n\n const parts = v.split(/\\s+/).filter(Boolean);\n const isCount = (p: string) => /^-?(\\d+\\.?\\d*|\\.\\d+)$/.test(p);\n const [a, b, c] = parts;\n if (!a) return {};\n if (parts.length === 1) return isCount(a) ? { grow: num(a), shrink: 1, basis: 0 } : { grow: 1, shrink: 1, basis: length(a) };\n if (parts.length === 2) {\n return isCount(b!) ? { grow: num(a), shrink: num(b!), basis: 0 } : { grow: num(a), shrink: 1, basis: length(b!) };\n }\n return { grow: num(a), shrink: num(b!), basis: length(c!) };\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 const f = flexShorthand(value);\n set(\"flexGrow\", f.grow);\n set(\"flexShrink\", f.shrink);\n set(\"flexBasis\", f.basis);\n break;\n }\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 // A text node's link goes in its kind, not beside it. The engine reads a View's\n // link from the node and a Text's from `kind.href`, and an `href` beside a Text's\n // kind is ignored without a warning — so every link in text, the free plan's\n // credit line included, used to arrive in a tree that looked right and leave a\n // file with no link in it. Found by rendering both shapes and counting the link\n // annotations; `tests/pdf/watermark.test.ts` opens a finished file to hold it.\n if (v.tag === \"a\" && typeof v.props.href === \"string\") kind.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 // A copy of each entry, never the caller's own. The engine resolves fonts in\n // place — bytes become a bare base64 string, which the *next* render then\n // reads as a path or fetches as a URL — so handing it this array made the first\n // measurement work and every later one throw. `fontEntries` in api.ts copies\n // for the same reason.\n if (this.opts.fonts?.length) doc.fonts = this.opts.fonts.map((f) => ({ ...(f as Record<string, unknown>) }));\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 * The theme's fonts, made into fonts the engine can embed.\n *\n * A host declares a font once, in `theme.fonts`. The browser has always read that\n * declaration — `@font-face` rules on the canvas, the designer's font pickers, the\n * validator, the Chromium backend — and this engine did not: it took a separate\n * `fonts` option, so a font declared only in the theme was drawn on screen and\n * measured and printed in the standard faces. Nothing said so, and the symptom was\n * a canvas whose sections overlapped and a PDF whose lines broke somewhere else.\n *\n * Three things stand between a `@font-face` declaration and the engine.\n *\n * **Format.** The engine parses TrueType and OpenType and nothing else; there is no\n * WOFF decoder in it. A face often lists a WOFF2 for the browser beside a TTF, so\n * the first source the engine can read is the one it gets, and a WOFF is skipped by\n * its name before anything is downloaded. What is downloaded is checked by its\n * first four bytes, not its extension. A face with nothing readable is a warning,\n * because the alternative is exactly the silence described above.\n *\n * **Where it comes from.** A theme is the host's own code in the SDK and a JSON body\n * from a stranger in the render service, so the service narrows `FontSourcePolicy`\n * to its allowed hosts and to no files at all. The SDK default is to trust the\n * theme, as it trusts the template.\n *\n * **Doing it once.** The engine resolves a font by rewriting its entry in place,\n * and re-reads anything that is not a `data:` URI on every render. Every source is\n * therefore resolved here, once per address, to a `data:` URI the engine passes\n * straight through.\n */\nimport type { Theme, ThemeFontFace } from \"@broadpaper/core\";\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\n/** Where the theme's fonts may be read from. */\nexport interface FontSourcePolicy {\n /** Hosts an `http(s)` font may be fetched from; `\"*\"` for any. Unset means any. */\n allowedHosts?: string[];\n /**\n * Whether a source that is neither `data:` nor `http(s)` may be read — a file in\n * Node, an address relative to the page in a browser. Default true.\n */\n local?: boolean;\n}\n\n/** Reads a source that is neither `data:` nor `http(s)`. Installed by each entry point. */\nexport type FontFileReader = (src: string) => Promise<Uint8Array>;\n\nlet localReader: FontFileReader | null = null;\n\n/**\n * Installs the reader for local sources. `src/index.ts` reads files and\n * `src/index.browser.ts` fetches relative to the page, and neither bundle contains\n * the other's — the same arrangement as `setEngineLoader`.\n */\nexport function setFontFileReader(reader: FontFileReader): void {\n localReader = reader;\n}\n\nexport interface ResolvedFonts {\n fonts: FormeFont[];\n warnings: string[];\n}\n\n/** Larger than any single face in use, CJK included; a guard against a runaway response, not a style rule. */\nconst MAX_FONT_BYTES = 32 * 1024 * 1024;\nconst FETCH_TIMEOUT_MS = 15_000;\n/** Addresses whose resolution is kept. A long-running service meets a bounded set of brands. */\nconst MAX_CACHED = 64;\n\ntype Loaded = { src: string } | { reason: string };\n\nconst cache = new Map<string, Promise<Loaded>>();\n\n/**\n * The fonts to hand the engine: the caller's own `fonts` first, exactly as given,\n * then every face in the theme the engine can read.\n *\n * The first entry for a family, weight and style wins, so an explicit font — or a\n * service's own — is never displaced by a theme naming the same face.\n */\nexport async function resolveFonts(input: { fonts?: FormeFont[]; theme?: Partial<Theme>; sources?: FontSourcePolicy }): Promise<ResolvedFonts> {\n const fonts: FormeFont[] = [];\n const warnings: string[] = [];\n const seen = new Set<string>();\n const add = (font: FormeFont) => {\n const weight = font.weight ?? 400;\n const style = font.style ?? \"normal\";\n const key = `${font.family.trim().toLowerCase()}|${weight}|${style}`;\n if (seen.has(key)) return;\n seen.add(key);\n fonts.push({ family: font.family, src: font.src, weight, style });\n };\n\n for (const font of input.fonts ?? []) add(font);\n const faces = await Promise.all((input.theme?.fonts ?? []).map((face) => themeFace(face, input.sources ?? {})));\n for (const face of faces) {\n warnings.push(...face.warnings);\n if (face.font) add(face.font);\n }\n return { fonts, warnings };\n}\n\nasync function themeFace(face: ThemeFontFace, policy: FontSourcePolicy): Promise<{ font?: FormeFont; warnings: string[] }> {\n const { weight, range } = weightOf(face.weight);\n const style = face.style === \"italic\" ? \"italic\" : \"normal\";\n const name = `\"${face.family}\" (${weight}${style === \"italic\" ? \" italic\" : \"\"})`;\n const sources = (Array.isArray(face.src) ? face.src : [face.src]).filter((s): s is string => typeof s === \"string\" && s.trim() !== \"\");\n\n const reasons: string[] = [];\n for (const src of sources) {\n const loaded = await load(src.trim(), policy);\n if (\"reason\" in loaded) {\n reasons.push(loaded.reason);\n continue;\n }\n const warnings = range\n ? [`The font \"${face.family}\" declares the weights ${String(face.weight)} from one file; the PDF engine is given it at ${weight} only. Declare a file per weight for the others to be embedded.`]\n : [];\n return { font: { family: face.family, src: loaded.src, weight, style }, warnings };\n }\n return {\n warnings: [\n `The font ${name} has no TrueType or OpenType source the PDF engine can read, so the PDF draws that text in a standard face and breaks its lines differently from the screen. ` +\n `Add a .ttf or .otf to its src${reasons.length ? ` (${reasons.join(\"; \")})` : \"\"}.`\n ]\n };\n}\n\n/** A CSS font-weight, as the single number the engine takes. A range is a variable font. */\nfunction weightOf(value: ThemeFontFace[\"weight\"]): { weight: number; range: boolean } {\n if (typeof value === \"number\" && Number.isFinite(value)) return { weight: Math.round(value), range: false };\n const text = String(value ?? \"\").trim().toLowerCase();\n if (text === \"bold\") return { weight: 700, range: false };\n const numbers = text.split(/\\s+/).map(Number).filter((n) => Number.isFinite(n) && n > 0);\n if (!numbers.length) return { weight: 400, range: false };\n return { weight: Math.round(numbers[0]!), range: numbers.length > 1 && numbers[1] !== numbers[0] };\n}\n\nasync function load(src: string, policy: FontSourcePolicy): Promise<Loaded> {\n // By name, before anything is fetched: a face's WOFF2 is for the browser beside it.\n if (/^data:(font|application)\\/(x-)?woff2?[;,]/i.test(src) || /\\.woff2?([?#]|$)/i.test(src.startsWith(\"data:\") ? \"\" : src)) {\n return { reason: `${describe(src)} is WOFF, which only a browser reads` };\n }\n\n if (src.startsWith(\"data:\")) return fromDataUri(src);\n\n const remote = /^https?:\\/\\//i.test(src);\n if (remote) {\n let host: string;\n try {\n host = new URL(src).hostname;\n } catch {\n return { reason: `${describe(src)} is not a valid address` };\n }\n const allowed = policy.allowedHosts;\n if (allowed && !allowed.includes(\"*\") && !allowed.includes(host)) return { reason: `${host} is not an allowed host` };\n } else if (policy.local === false) {\n return { reason: `${describe(src)} is neither a data: URI nor a web address, and files are not read here` };\n } else if (!localReader) {\n // No entry point installed a reader — a caller importing the module directly.\n // The engine resolves such a source itself, which is what it did before.\n return { src };\n }\n\n const key = src;\n const hit = cache.get(key);\n if (hit) return hit;\n const pending = (async (): Promise<Loaded> => {\n const bytes = remote ? await download(src, Boolean(policy.allowedHosts && !policy.allowedHosts.includes(\"*\"))) : await localReader!(src);\n if (bytes.byteLength > MAX_FONT_BYTES) return { reason: `${describe(src)} is larger than ${MAX_FONT_BYTES / 1024 / 1024} MB` };\n const problem = notEmbeddable(bytes, src);\n return problem ? { reason: problem } : { src: `data:font/ttf;base64,${toBase64(bytes)}` };\n })().catch((e: unknown) => {\n // A failure is not kept: the next render tries again rather than failing for the\n // life of the process.\n cache.delete(key);\n return { reason: `${describe(src)} could not be read (${(e as Error).message || String(e)})` };\n });\n cache.set(key, pending);\n while (cache.size > MAX_CACHED) cache.delete(cache.keys().next().value!);\n return pending;\n}\n\nasync function download(src: string, restricted: boolean): Promise<Uint8Array> {\n const signal = typeof AbortSignal !== \"undefined\" && \"timeout\" in AbortSignal ? AbortSignal.timeout(FETCH_TIMEOUT_MS) : undefined;\n // A redirect would take a restricted fetch to a host nobody checked.\n const response = await fetch(src, { redirect: restricted ? \"error\" : \"follow\", ...(signal ? { signal } : {}) });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const length = Number(response.headers.get(\"content-length\"));\n if (length > MAX_FONT_BYTES) throw new Error(`larger than ${MAX_FONT_BYTES / 1024 / 1024} MB`);\n return new Uint8Array(await response.arrayBuffer());\n}\n\nfunction fromDataUri(src: string): Loaded {\n const match = /^data:([^,]*),(.*)$/s.exec(src);\n if (!match) return { reason: \"a data: URI with no data\" };\n const base64 = /;base64$/i.test(match[1]!);\n let head: Uint8Array;\n try {\n head = base64 ? fromBase64(match[2]!.slice(0, 8)) : Uint8Array.from(decodeURIComponent(match[2]!.slice(0, 64)), (c) => c.charCodeAt(0) & 0xff);\n } catch {\n return { reason: \"a data: URI that does not decode\" };\n }\n const problem = notEmbeddable(head, \"a data: URI\");\n if (problem) return { reason: problem };\n if (base64) return { src };\n // The engine only takes the base64 form.\n const bytes = Uint8Array.from(decodeURIComponent(match[2]!), (c) => c.charCodeAt(0) & 0xff);\n return { src: `data:font/ttf;base64,${toBase64(bytes)}` };\n}\n\n/** Null when these are TrueType or OpenType bytes, otherwise why not. */\nfunction notEmbeddable(bytes: Uint8Array, src: string): string | null {\n if (bytes.length < 4) return `${describe(src)} is not a font file`;\n const tag = String.fromCharCode(bytes[0]!, bytes[1]!, bytes[2]!, bytes[3]!);\n if ((bytes[0] === 0 && bytes[1] === 1 && bytes[2] === 0 && bytes[3] === 0) || tag === \"OTTO\" || tag === \"true\") return null;\n if (tag === \"wOFF\" || tag === \"wOF2\") return `${describe(src)} is WOFF, which only a browser reads`;\n if (tag === \"ttcf\") return `${describe(src)} is a font collection; give the single face instead`;\n return `${describe(src)} is not a TrueType or OpenType file`;\n}\n\nfunction describe(src: string): string {\n return src.startsWith(\"data:\") ? \"a data: URI\" : src.length > 80 ? `${src.slice(0, 77)}…` : src;\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return btoa(binary);\n}\n\nfunction fromBase64(text: string): Uint8Array {\n const clean = text.replace(/[^A-Za-z0-9+/]/g, \"\");\n const binary = atob(clean.slice(0, clean.length - (clean.length % 4)));\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\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, Theme } from \"@broadpaper/core\";\nimport { resolveFonts, type FormeFont } from \"./fonts.js\";\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 /**\n * Fonts for the engine beyond the theme's own.\n *\n * Usually unnecessary: the faces in `theme.fonts` are read and given to the\n * engine without being named here. May be a promise, because a browser host has\n * to fetch the files and `createMeasurer` has to return synchronously. Every\n * measurement waits for it, so nothing is ever measured — and cached — with the\n * engine's standard faces standing in for a font that was still arriving.\n */\n fonts?: unknown[] | Promise<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, faces: string): string {\n return hash(JSON.stringify(section)) + \":\" + Math.round(width * 100) + \":\" + mode + \":\" + faces;\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 // A section measured in one theme's fonts is a different height in another's.\n const faces = facesKey(opts.theme.fonts);\n for (const section of sections) {\n const k = this.key(section, width, opts.mode, faces);\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 const given = await this.config.fonts;\n const { fonts, warnings } = await resolveFonts({ fonts: given as FormeFont[] | undefined, theme: opts.theme });\n for (const w of warnings) this.warn(w);\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,\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) this.warn(w);\n return out;\n }\n\n private warn(message: string): void {\n if (this.seen.has(message)) return;\n this.seen.add(message);\n this.config.onWarning?.(message);\n }\n}\n\n/** Which faces a theme declares, cheaply: a data: URI can be megabytes, so only its ends are read. */\nfunction facesKey(faces: Theme[\"fonts\"]): string {\n if (!faces?.length) return \"\";\n return hash(\n faces\n .map((f) => [f.family, f.weight, f.style, ...(Array.isArray(f.src) ? f.src : [f.src]).map((s) => `${s.length}:${s.slice(0, 64)}${s.slice(-64)}`)].join(\"|\"))\n .join(\";\")\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, type WatermarkSpec } from \"@broadpaper/license\";\nimport { vnodeToForme, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { creditNode } from \"./credit.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\nimport { resolveFonts, type FontSourcePolicy, type FormeFont } from \"./fonts.js\";\nexport { resolveFonts, setFontFileReader } from \"./fonts.js\";\nexport type { FontFileReader, FontSourcePolicy, FormeFont, ResolvedFonts } from \"./fonts.js\";\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 /**\n * Fonts handed to the engine as they are, before the theme's.\n *\n * Most hosts need none: every face in `theme.fonts` with a TrueType or OpenType\n * source is embedded without being named twice. This is for a font the theme\n * does not declare — one a service embeds in every render, say.\n */\n fonts?: FormeFont[];\n /** Where the theme's fonts may be read from. Unset, anywhere: a host's own theme is trusted. */\n fontSources?: FontSourcePolicy;\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 * An extra mark to draw behind every page, on top of whatever the licence\n * decides.\n *\n * Additive and never a replacement: the licence mark is decided by\n * `watermarkFor` and this cannot remove it, which is the property that keeps\n * \"a caller cannot reach a PDF without passing the licence check\" true. It\n * exists for a host whose own commercial model wants a mark — BroadPaper Cloud\n * marks the documents its free plan produces — and for the ordinary \"DRAFT\"\n * stamp a business document sometimes needs.\n *\n * Remember that an unstyled Forme watermark draws solid black at full opacity;\n * a spec without a colour and an opacity makes the document unreadable.\n */\n watermark?: WatermarkSpec | null;\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 // The licence mark first, then anything the caller added. The caller cannot\n // replace the first one, only sit beside it.\n const marks = [watermarkFor(license), opts.watermark].filter((m): m is WatermarkSpec => Boolean(m));\n for (const mark of marks) if ((mark.placement ?? \"center\") === \"center\") 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 /*\n * A credit line goes in the footer region on this path, not in the margin.\n *\n * The paginated path draws it in the bottom margin, where it costs no layout.\n * Here pagination belongs to the engine — this is one wrapping Page node — so\n * there is nothing to position against and no page count to repeat over, and\n * the only primitives that recur on every page are the watermark node and the\n * Fixed regions. A footer line is the honest one of the two: a `bottom`\n * placement exists precisely because a stamp in the middle of the page was\n * wrong, and degrading it back to that would be answering the wrong question.\n */\n const credits = marks\n .filter((m) => (m.placement ?? \"center\") === \"bottom\")\n .map((m) => creditNode(m, geom.contentWidth, ctx))\n .filter((n): n is FormeNode => Boolean(n));\n if (footer.length || credits.length) {\n children.push({ kind: { type: \"Fixed\", position: \"Footer\" }, style: {}, children: [...footer, ...credits] });\n }\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 const fonts = await resolveFonts({ fonts: opts.fonts, theme, sources: opts.fontSources });\n if (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 warnings = [...ctx.warnings, ...resolved.warnings.map((w) => w.message), ...fonts.warnings];\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, type SectionGeometry, type VNode } from \"@broadpaper/core\";\nimport { translate } from \"./vnode.js\";\nimport { longTables, sliceTables, stitchTables, type LongTable } from \"./long-tables.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: LayoutPaginatedOptions): Promise<RenderPaginatedResult> {\n const started = Date.now();\n const layout = await layoutPaginated(opts);\n const drawn = await layout.draw();\n return {\n pdf: drawn.pdf,\n pages: drawn.pages,\n layout: drawn.layout,\n paged: layout.paged,\n geometry: layout.geometry,\n warnings: drawn.warnings,\n durationMs: Date.now() - started\n };\n}\n\n/** A table longer than this many body rows is measured a batch at a time. */\nexport const MEASURE_BATCH_ROWS = 1_000;\n\nexport interface LayoutPaginatedOptions extends RenderFormePdfOptions {\n /**\n * Body rows per measuring pass for a long table. Only a test should change it:\n * a small number exercises the batching on a table short enough to compare with\n * measuring it whole.\n */\n measureBatchRows?: number;\n}\n\n/** A document laid out and paginated, and not yet drawn. */\nexport interface PaginatedLayout {\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 * Draws pages `[from, to)` — the whole document when no range is given — as one\n * PDF. Pages keep their numbers in the whole document, so page 251 of a split\n * document still says \"251 of 1,300\".\n */\n draw(range?: { from: number; to: number }): Promise<{ pdf: Uint8Array; pages: number; layout: { pages: FormePageInfo[] } | null; warnings: string[] }>;\n}\n\n/**\n * Resolves, measures and paginates without drawing.\n *\n * Separate from drawing for two reasons a long document made plain. The page\n * count is known here, before the more expensive half of the work, so a caller\n * with a ceiling can refuse or split first rather than after; and a document of\n * a thousand pages can be drawn as several files from one layout, every one of\n * them agreeing about where the page breaks fall and what the totals are.\n */\nexport async function layoutPaginated(opts: LayoutPaginatedOptions): Promise<PaginatedLayout> {\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 // Once, for every pass: measuring and drawing must be given the same faces, or the\n // second re-breaks what the first measured.\n const fonts = await resolveFonts({ fonts: opts.fonts, theme, sources: opts.fontSources });\n\n /** Lays these trees out on one unbounded page and reads their geometry back. */\n const layoutSections = async (list: Array<{ section: ResolvedNode; tree: VNode }>): Promise<GeometryMap> => {\n if (!list.length) return {};\n const measured: MeasuredSection[] = [];\n for (const { section, tree } of list) {\n const t = translate(tree, 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 (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 /*\n * Measures sections, with any table too long for one pass measured a batch of\n * rows at a time — see `long-tables.ts` for why one pass is wrong past about ten\n * thousand rows, not merely slow.\n */\n const batchRows = Math.max(1, opts.measureBatchRows ?? MEASURE_BATCH_ROWS);\n const measure = async (sections: ResolvedNode[]): Promise<GeometryMap> => {\n const parts: Array<{ section: ResolvedNode; tree: VNode; long: LongTable[] }> = [];\n for (const section of sections) {\n const tree = renderNode(section, renderOpts, geom.contentWidth);\n if (tree) parts.push({ section, tree, long: longTables(tree, batchRows) });\n }\n const out = await layoutSections(parts.map((p) => ({ section: p.section, tree: p.long.length ? sliceTables(p.tree, p.long, 0, batchRows) : p.tree })));\n\n for (const p of parts) {\n const first = out[p.section.key];\n if (!p.long.length || !first) continue;\n const most = Math.max(...p.long.map((t) => t.bodyRows));\n const batches: Array<{ section: ResolvedNode; tree: VNode }> = [];\n for (let start = batchRows; start < most; start += batchRows) {\n // A key of its own per batch, so several batches can share one pass.\n batches.push({ section: { ...p.section, key: `${p.section.key}#rows-${start}` }, tree: sliceTables(p.tree, p.long, start, batchRows) });\n }\n const measured: SectionGeometry[] = [];\n for (let i = 0; i < batches.length; i += BATCHES_PER_PASS) {\n const chunk = batches.slice(i, i + BATCHES_PER_PASS);\n const got = await layoutSections(chunk);\n for (const b of chunk) {\n const g = got[b.section.key];\n if (g) measured.push(g);\n }\n }\n out[p.section.key] = stitchTables(first, p.long, measured);\n }\n return out;\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 const background = template.page.background ? resolveValue(template.page.background, theme, \"#ffffff\") : undefined;\n\n return {\n paged,\n geometry,\n async draw(range) {\n const from = Math.max(0, range?.from ?? 0);\n const to = Math.min(paged.pages.length, range?.to ?? paged.pages.length);\n const pages = emitPages({\n resolved,\n // `totalPages` stays the whole document's, so a later file still counts\n // its pages as part of the whole.\n paged: { ...paged, pages: paged.pages.slice(from, to) },\n page: geom,\n renderOpts,\n ctx,\n geometry,\n background,\n watermarks: [watermarkFor(license), opts.watermark]\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 (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 ?? to - from,\n layout,\n warnings: [...ctx.warnings, ...resolved.warnings.map((w) => w.message), ...paged.warnings.map((w) => w.message), ...fonts.warnings, ...(result.warnings ?? [])]\n };\n }\n };\n}\n\n/**\n * Batches laid out together in one engine pass. Two thousand ordinary rows is\n * well inside the measuring page's height; a table whose rows are each many\n * lines tall is the case that would need fewer.\n */\nconst BATCHES_PER_PASS = 2;\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 * A credit line: an optional small mark, then the text.\n *\n * `WatermarkSpec` with `placement: \"bottom\"` — the shape a host's own commercial\n * model usually wants, as distinct from the evaluation mark's diagonal stamp.\n * BroadPaper Cloud's free plan started as a `center` mark at eight points, which\n * is a small grey sentence floating in the middle of an otherwise finished\n * invoice: it reads as a mistake rather than as a credit, and the point of that\n * mark is that a free user's document stays sendable.\n *\n * Built as a VNode and put through the ordinary translator rather than assembled\n * as engine nodes by hand, which buys two things that are easy to get wrong: the\n * mark's SVG data URI is decoded and re-emitted as vector drawing — the engine's\n * image decoder cannot read an SVG and leaves a grey box where the logo should\n * be — and the sizing lands in the style box as well as in the node, which an SVG\n * needs or it is laid out as auto and takes whatever room is going.\n *\n * The text carries its own colour and size explicitly. This is a flex container,\n * so it translates to a View, and text styles do not inherit through a View.\n *\n * Both render paths use this: the paginated one draws it in the bottom margin,\n * where it costs no layout, and the engine-paginated one puts it in the Fixed\n * footer region, which is the only thing that recurs per page there.\n */\nimport type { VNode } from \"@broadpaper/core\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport { translate, type FormeNode, type TranslateContext } from \"./vnode.js\";\n\nexport function creditNode(spec: WatermarkSpec, width: number, ctx: TranslateContext): FormeNode | null {\n const size = spec.fontSize;\n const children: VNode[] = [];\n\n if (spec.mark) {\n children.push({\n tag: \"img\",\n props: { src: spec.mark, alt: \"\", style: { width: `${size}px`, height: `${size}px`, opacity: String(spec.opacity) } },\n children: []\n });\n }\n\n // An anchor when the spec names an address, which the translator turns into a\n // link on the text node — the same path a link in a report's own rich text takes.\n children.push({\n tag: spec.href ? \"a\" : \"span\",\n props: {\n ...(spec.href ? { href: spec.href } : {}),\n style: { \"font-size\": `${size}px`, color: spec.color, opacity: String(spec.opacity), \"line-height\": \"1.2\" }\n },\n children: [spec.text]\n });\n\n const line: VNode = {\n tag: \"div\",\n props: {\n style: {\n display: \"flex\",\n \"align-items\": \"center\",\n gap: `${Math.max(2, Math.round(size * 0.5))}px`,\n width: `${width}px`,\n \"justify-content\": \"center\"\n }\n },\n children\n };\n\n return translate(line, ctx)?.node ?? null;\n}\n","/**\n * Measuring a long table a batch of rows at a time.\n *\n * The measuring pass lays a section out on one page `UNBOUNDED_PAGE_HEIGHT`\n * points tall and reads the geometry back. That page is not unbounded: at twenty\n * points a row, a table of ten thousand rows is taller than it, and the engine\n * truncates anything taller than the page it is drawn on — so the paginator was\n * handed a table that ended where the page did, and twelve thousand rows came out\n * as a one-page PDF with no warning. The engine's layout time also grows faster\n * than the number of rows on one page, so one enormous pass was the slowest way to\n * measure even before it was wrong.\n *\n * So a section holding a table longer than a batch is measured several times:\n * once with every long table cut to its first batch of body rows, which places\n * everything else in the section, and once per further batch. The rows are then\n * joined back into one table's geometry and everything below the table moved down\n * by the height the extra rows take.\n *\n * Row heights do not depend on the rows around them — widths come from the\n * column definitions and the table's own width, which every pass shares — which\n * is what makes measuring them apart the same as measuring them together.\n */\nimport type { NodeGeometry, SectionGeometry, TableRowGeometry, VNode } from \"@broadpaper/core\";\n\n/** A table in a rendered section with more body rows than one pass takes. */\nexport interface LongTable {\n table: VNode;\n /** The nearest keyed node holding the table, which is where its rows are measured. */\n key: string;\n bodyRows: number;\n}\n\nconst EPS = 0.5;\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction isRow(c: VNode | string): c is VNode {\n return typeof c !== \"string\" && c.tag === \"tr\";\n}\n\n/** Body rows, counted the way the translator assigns them: `tbody` rows and bare rows. */\nfunction bodyRowCount(table: VNode): number {\n let n = 0;\n for (const c of table.children) {\n if (typeof c === \"string\") continue;\n if (c.tag === \"tbody\") n += c.children.filter(isRow).length;\n else if (c.tag === \"tr\") n++;\n }\n return n;\n}\n\n/** Every table under `tree` with more than `limit` body rows, and the key its rows are measured under. */\nexport function longTables(tree: VNode, limit: number): LongTable[] {\n const out: LongTable[] = [];\n const visit = (v: VNode, key: string | undefined) => {\n const own = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : key;\n if (v.tag === \"table\") {\n const rows = bodyRowCount(v);\n // A table with no keyed ancestor has no geometry to join rows into, and\n // is measured whole as it always was.\n if (rows > limit && own) out.push({ table: v, key: own, bodyRows: rows });\n return;\n }\n for (const c of v.children) if (typeof c !== \"string\") visit(c, own);\n };\n visit(tree, undefined);\n return out;\n}\n\n/** `tree` with each long table's body rows narrowed to `[start, start + count)`; header and footer rows kept. */\nexport function sliceTables(tree: VNode, tables: LongTable[], start: number, count: number): VNode {\n const targets = new Set(tables.map((t) => t.table));\n const visit = (v: VNode): VNode => {\n if (targets.has(v)) return sliceRows(v, start, count);\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = visit(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n };\n return visit(tree);\n}\n\nfunction sliceRows(table: VNode, start: number, count: number): VNode {\n let index = 0;\n const keep = () => {\n const i = index++;\n return i >= start && i < start + count;\n };\n const children: Array<VNode | string> = [];\n for (const c of table.children) {\n if (typeof c === \"string\") children.push(c);\n else if (c.tag === \"tbody\") children.push({ ...c, children: c.children.filter((r) => !isRow(r) || keep()) });\n else if (c.tag === \"tr\") {\n if (keep()) children.push(c);\n } else children.push(c);\n }\n return { ...table, children };\n}\n\nfunction sameRows(a: TableRowGeometry[] | undefined, b: TableRowGeometry[]): boolean {\n return !!a && a.length === b.length && a[0]?.top === b[0]?.top && a[a.length - 1]?.top === b[b.length - 1]?.top;\n}\n\n/**\n * The section's geometry with every long table's remaining rows joined in.\n *\n * `first` is the section measured with each long table cut to its first batch;\n * `batches` are the later batches, in order, each measured as the same section\n * with only that batch's rows. Tables are joined from the lowest up, so moving the\n * content under an upper table also moves a lower table that has already grown.\n */\nexport function stitchTables(first: SectionGeometry, tables: LongTable[], batches: SectionGeometry[]): SectionGeometry {\n const g: SectionGeometry = {\n ...first,\n nodes: Object.fromEntries(Object.entries(first.nodes).map(([k, n]) => [k, { ...n } as NodeGeometry]))\n };\n const bottomOf = (rows: TableRowGeometry[]) => Math.max(...rows.map((r) => r.top + r.height));\n const order = tables\n .map((t) => ({ t, rows: first.nodes[t.key]?.rows }))\n .filter((x): x is { t: LongTable; rows: TableRowGeometry[] } => !!x.rows && x.rows.some((r) => r.kind === \"body\"))\n .sort((a, b) => bottomOf(b.rows) - bottomOf(a.rows));\n\n for (const { t } of order) {\n const main = g.nodes[t.key]!.rows!;\n const body = main.filter((r) => r.kind === \"body\");\n const last = body[body.length - 1]!;\n const bodyEnd = last.top + last.height;\n // Whatever separates one row from the next — border spacing, usually nothing —\n // separates the batches too.\n const gap = body.length > 1 ? Math.max(0, body[1]!.top - (body[0]!.top + body[0]!.height)) : 0;\n\n const extra: TableRowGeometry[] = [];\n let cursor = bodyEnd + gap;\n for (const batch of batches) {\n const rows = batch.nodes[t.key]?.rows?.filter((r) => r.kind === \"body\") ?? [];\n if (!rows.length) continue;\n const base = rows[0]!.top;\n for (const r of rows) extra.push({ top: round(cursor + r.top - base), height: r.height, kind: \"body\" });\n const end = rows[rows.length - 1]!;\n cursor += end.top + end.height - base + gap;\n }\n if (!extra.length) continue;\n\n const tail = extra[extra.length - 1]!;\n const delta = round(tail.top + tail.height - bodyEnd);\n const merged: TableRowGeometry[] = [\n ...main.filter((r) => r.kind === \"header\"),\n ...body,\n ...extra,\n ...main.filter((r) => r.kind === \"footer\").map((r) => ({ ...r, top: round(r.top + delta) }))\n ];\n\n for (const n of Object.values(g.nodes)) {\n // Every keyed wrapper of the table carries its rows, because the translator\n // lifts row roles onto the nearest keyed node and each ancestor adopts them.\n const holdsThisTable = sameRows(n.rows, main);\n if (n.top >= bodyEnd - EPS) {\n n.top = round(n.top + delta);\n if (n.lines) n.lines = n.lines.map((y) => round(y + delta));\n if (n.rows && !holdsThisTable) n.rows = n.rows.map((r) => ({ ...r, top: round(r.top + delta) }));\n } else if (n.top + n.height > bodyEnd - EPS) {\n n.height = round(n.height + delta);\n }\n if (holdsThisTable) n.rows = merged;\n }\n g.height = round(g.height + delta);\n }\n return g;\n}\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 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 { creditNode } from \"./credit.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/**\n * Strips a rendered table down to its header rows, for repeating across pages.\n *\n * Copies only the path down to each table rather than cloning the tree: a deep\n * clone of a fifty-thousand-row table to keep its one header row was most of the\n * cost of a long document. Nothing downstream mutates a VNode, so the untouched\n * branches are shared.\n */\nfunction headerOnly(v: VNode): VNode {\n if (v.tag === \"table\") {\n return { ...v, children: v.children.filter((c) => typeof c !== \"string\" && (c.tag === \"colgroup\" || c.tag === \"thead\")) };\n }\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = headerOnly(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\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 * Marks to draw behind the content, in order.\n *\n * A list rather than one, because two separate decisions can each ask for a\n * mark and neither may cancel the other: the licence decides whether the\n * output carries the evaluation mark, and a host — BroadPaper Cloud is the\n * first — may add one of its own for its own commercial reasons. Collapsing\n * them into a single slot is how the licence mark eventually gets overwritten\n * by somebody who only meant to add a \"DRAFT\".\n *\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 watermarks?: Array<WatermarkSpec | null | undefined>;\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 /*\n * The section's tree, rendered once and cropped once per page.\n *\n * Rendering it again for every window made a long table quadratic: each of a\n * hundred pages re-rendered all four thousand rows only for the crop to throw\n * all but forty away, and at fifty thousand rows that step alone ran for tens of\n * minutes. `cropToWindow` never mutates its input, so one tree serves every page\n * — unless the body reads `page.*`, where each page needs its own.\n */\n const rendered = new Map<string, VNode | null>();\n const treeOf = (section: ResolvedNode, opts: RenderTreeOptions): VNode | null => {\n if (bodyDependsOnPage) return renderNode(section, opts, width);\n if (!rendered.has(section.key)) rendered.set(section.key, renderNode(section, opts, width));\n return rendered.get(section.key)!;\n };\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 = treeOf(section, opts);\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 /*\n * A table's repeated header, drawn once per table and reused on every page.\n *\n * It used to render the whole table afresh on every continuation page and copy\n * all of it to keep the header rows — at two thousand rows that was four seconds\n * of a twenty-second render, and it grew with rows times pages.\n */\n const headers = new Map<string, FormeNode | null>();\n const repeatedHeader = (tableKey: string, table: ResolvedNode, opts: RenderTreeOptions, headerWidth: number): FormeNode | null => {\n const key = `${tableKey}|${headerWidth}`;\n if (!bodyDependsOnPage && headers.has(key)) return headers.get(key)!;\n const v = renderNode(table, opts, headerWidth);\n const t = v ? translate(headerOnly(v), ctx) : null;\n const node = t ? t.node : null;\n if (!bodyDependsOnPage) headers.set(key, node);\n return node;\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 marks are under the report and not across it.\n for (const mark of input.watermarks ?? []) if (mark && (mark.placement ?? \"center\") === \"center\") children.push(watermarkNode(mark));\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 header = repeatedHeader(r.tableKey, table, opts, r.width);\n if (header) inner.push(box(r.left, 0, r.width, r.height, [header]));\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 /*\n * A credit line along the foot of the page.\n *\n * In the bottom margin rather than in the footer band, and that is the whole\n * reason it is here and not injected into the template: a mark that took\n * content height would make the finished file paginate differently from the\n * canvas the user approved, and the margin is the one part of the page nothing\n * else lays out in.\n *\n * After the content, unlike the diagonal stamp, because it sits in a margin\n * where there is nothing to be under.\n */\n for (const mark of input.watermarks ?? []) {\n if (!mark || (mark.placement ?? \"center\") !== \"bottom\") continue;\n const node = creditNode(mark, width, ctx);\n if (!node) continue;\n const h = mark.fontSize * 1.6;\n // Centred in the bottom margin, or sitting on the page edge when the margin\n // is too shallow to centre anything in.\n const top = Math.max(page.height - h, page.height - page.margins.bottom + Math.max(0, (page.margins.bottom - h) / 2));\n children.push(box(page.margins.left, top, width, h, [node]));\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 * - The run of blocks wholly above the window, at the start of a stack of\n * siblings, is removed. The first block that stays moves up to where the first\n * removed one began — a distance the geometry gives exactly, gaps and all — and\n * that distance is added to `offset`.\n * - Any other node wholly outside the window becomes an empty box of exactly the\n * height 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 — added to the same `offset`,\n * so the page can take it off the shift it was going to apply.\n *\n * The removal is not tidiness. Keeping full-height boxes above the window made a\n * section's third page a node three pages tall with the page's content at the\n * bottom of it, and the engine's truncation then moved that content up and\n * dropped the first blocks it held — an imported invoice lost a heading and six\n * table rows from its second page, with no warning. Emptying the boxes to zero\n * height is not enough either: a stack's `gap` survives between empty boxes, and\n * a hundred of them still push the page's content past the page. Only stacks are\n * trimmed: in columns side by side, removing one column's blocks would move that\n * column and not its neighbour, and there is no single offset to report.\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, true);\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\n/**\n * @param stacked whether `v` and everything above it up to the section sit in a\n * single column, so that removing height from `v` moves everything after it by\n * exactly that much.\n */\nfunction crop(v: VNode, w: Window, rows: TableRowGeometry[] | undefined, stacked: boolean): VNode {\n const g = geometryOf(v, w.geom);\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 const childrenStacked = stacked && !sideBySide(v.children, w.geom);\n const removed = childrenStacked ? removeAbove(v.children, w) : 0;\n let changed = removed > 0;\n const children = v.children.slice(removed).map((c) => {\n if (typeof c === \"string\") return c;\n const next = crop(c, w, rows, childrenStacked);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n}\n\nfunction geometryOf(v: VNode, geom: SectionGeometry): SectionGeometry[\"nodes\"][string] | undefined {\n const key = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : undefined;\n return key ? geom.nodes[key] : undefined;\n}\n\n/** The vertical span a node's measured content covers, looking through unmeasured wrappers. */\nfunction extent(v: VNode, geom: SectionGeometry): [number, number] | null {\n const g = geometryOf(v, geom);\n if (g) return g.height > EPS ? [g.top, g.top + g.height] : null;\n let span: [number, number] | null = null;\n for (const c of v.children) {\n if (typeof c === \"string\") continue;\n const e = extent(c, geom);\n if (e) span = span ? [Math.min(span[0], e[0]), Math.max(span[1], e[1])] : e;\n }\n return span;\n}\n\n/** Whether any two of these siblings share a band of height — columns, not a stack. */\nfunction sideBySide(children: Array<VNode | string>, geom: SectionGeometry): boolean {\n const spans = children\n .filter((c): c is VNode => typeof c !== \"string\")\n .map((c) => extent(c, geom))\n .filter((e): e is [number, number] => e !== null)\n .sort((a, b) => a[0] - b[0]);\n let bottom = Number.NEGATIVE_INFINITY;\n for (const [top, end] of spans) {\n if (top < bottom - EPS) return true;\n bottom = Math.max(bottom, end);\n }\n return false;\n}\n\n/**\n * How many leading children of a stack lie wholly above the window, having added\n * the height their removal takes out to `w.dropped`.\n *\n * Measured from the geometry rather than summed from heights, because what sits\n * between the blocks — a stack's `gap`, their margins — is removed with them. The\n * first block that stays lands where the first removed one's margin box began,\n * plus its own top margin. When they are all removed, the stack closes up by the\n * whole run. A block without geometry of its own ends the run, since where it\n * would land cannot be read, and the blocks before it are left as empty boxes.\n */\nfunction removeAbove(children: Array<VNode | string>, w: Window): number {\n let start: number | null = null;\n let end = 0;\n let count = 0;\n for (let i = 0; i < children.length; i++) {\n const c = children[i]!;\n if (typeof c === \"string\") {\n if (c.trim()) return 0;\n continue;\n }\n const g = geometryOf(c, w.geom);\n if (!g) return 0;\n if (g.top + g.height > w.from + EPS) {\n if (start === null) return 0;\n w.dropped += g.top - margin(c, \"top\") - start;\n return i;\n }\n start ??= g.top - margin(c, \"top\");\n end = g.top + g.height + margin(c, \"bottom\");\n count = i + 1;\n }\n if (start === null) return 0;\n w.dropped += end - start;\n return count;\n}\n\n/** A node's top or bottom margin in pixels, from its inline style; zero for anything but pixels. */\nfunction margin(v: VNode, side: \"top\" | \"bottom\"): number {\n let value = 0;\n for (const declaration of styleString(v.props.style).split(\";\")) {\n const m = /^\\s*margin(?:-(top|bottom|left|right))?\\s*:\\s*(.+?)\\s*$/i.exec(declaration);\n if (!m) continue;\n if (m[1]) {\n if (m[1].toLowerCase() === side) value = pixels(m[2]!);\n } else {\n const parts = m[2]!.split(/\\s+/);\n value = pixels((side === \"top\" ? parts[0] : parts.length >= 3 ? parts[2] : parts[0])!);\n }\n }\n return value;\n}\n\nfunction pixels(length: string): number {\n const m = /^(-?\\d*\\.?\\d+)(px)?$/i.exec(length.trim());\n return m && (m[2] || Number(m[1]) === 0) ? Number(m[1]) : 0;\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","length","renderNode","mapStyle","resolveLicenseStatus","round","renderNode","mapStyle","styleString","EPS","length","round","mapStyle","cache","renderNode","translate","renderNode","mapStyle","scale"]}
@@ -23,7 +23,7 @@ import {
23
23
  verifyLicense,
24
24
  vnodeToForme,
25
25
  watermarkNode
26
- } from "./chunk-QA4APTWM.js";
26
+ } from "./chunk-FAKBQDQG.js";
27
27
 
28
28
  // src/engine.browser.ts
29
29
  import { init, renderSerializedDocWithLayout } from "@formepdf/core/worker";
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  verifyLicense,
24
24
  vnodeToForme,
25
25
  watermarkNode
26
- } from "./chunk-QA4APTWM.js";
26
+ } from "./chunk-FAKBQDQG.js";
27
27
 
28
28
  // src/engine.node.ts
29
29
  var readFontFile = async (path) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@broadpaper/forme",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
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
  "keywords": [
6
6
  "pdf",
@@ -50,9 +50,9 @@
50
50
  "dependencies": {
51
51
  "@formepdf/core": "^0.20.0",
52
52
  "@formepdf/shared": "^0.20.0",
53
- "@broadpaper/core": "0.4.0",
54
- "@broadpaper/license": "0.4.0",
55
- "@broadpaper/blocks": "0.4.0"
53
+ "@broadpaper/blocks": "0.4.1",
54
+ "@broadpaper/core": "0.4.1",
55
+ "@broadpaper/license": "0.4.1"
56
56
  },
57
57
  "browser": "./dist/index.browser.js",
58
58
  "scripts": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/style.ts","../src/vnode.ts","../src/svg.ts","../src/watermark.ts","../src/measure.ts","../src/fonts.ts","../src/editor.ts","../src/api.ts","../src/credit.ts","../src/long-tables.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 // A copy of each entry, never the caller's own. The engine resolves fonts in\n // place — bytes become a bare base64 string, which the *next* render then\n // reads as a path or fetches as a URL — so handing it this array made the first\n // measurement work and every later one throw. `fontEntries` in api.ts copies\n // for the same reason.\n if (this.opts.fonts?.length) doc.fonts = this.opts.fonts.map((f) => ({ ...(f as Record<string, unknown>) }));\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 * The theme's fonts, made into fonts the engine can embed.\n *\n * A host declares a font once, in `theme.fonts`. The browser has always read that\n * declaration — `@font-face` rules on the canvas, the designer's font pickers, the\n * validator, the Chromium backend — and this engine did not: it took a separate\n * `fonts` option, so a font declared only in the theme was drawn on screen and\n * measured and printed in the standard faces. Nothing said so, and the symptom was\n * a canvas whose sections overlapped and a PDF whose lines broke somewhere else.\n *\n * Three things stand between a `@font-face` declaration and the engine.\n *\n * **Format.** The engine parses TrueType and OpenType and nothing else; there is no\n * WOFF decoder in it. A face often lists a WOFF2 for the browser beside a TTF, so\n * the first source the engine can read is the one it gets, and a WOFF is skipped by\n * its name before anything is downloaded. What is downloaded is checked by its\n * first four bytes, not its extension. A face with nothing readable is a warning,\n * because the alternative is exactly the silence described above.\n *\n * **Where it comes from.** A theme is the host's own code in the SDK and a JSON body\n * from a stranger in the render service, so the service narrows `FontSourcePolicy`\n * to its allowed hosts and to no files at all. The SDK default is to trust the\n * theme, as it trusts the template.\n *\n * **Doing it once.** The engine resolves a font by rewriting its entry in place,\n * and re-reads anything that is not a `data:` URI on every render. Every source is\n * therefore resolved here, once per address, to a `data:` URI the engine passes\n * straight through.\n */\nimport type { Theme, ThemeFontFace } from \"@broadpaper/core\";\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\n/** Where the theme's fonts may be read from. */\nexport interface FontSourcePolicy {\n /** Hosts an `http(s)` font may be fetched from; `\"*\"` for any. Unset means any. */\n allowedHosts?: string[];\n /**\n * Whether a source that is neither `data:` nor `http(s)` may be read — a file in\n * Node, an address relative to the page in a browser. Default true.\n */\n local?: boolean;\n}\n\n/** Reads a source that is neither `data:` nor `http(s)`. Installed by each entry point. */\nexport type FontFileReader = (src: string) => Promise<Uint8Array>;\n\nlet localReader: FontFileReader | null = null;\n\n/**\n * Installs the reader for local sources. `src/index.ts` reads files and\n * `src/index.browser.ts` fetches relative to the page, and neither bundle contains\n * the other's — the same arrangement as `setEngineLoader`.\n */\nexport function setFontFileReader(reader: FontFileReader): void {\n localReader = reader;\n}\n\nexport interface ResolvedFonts {\n fonts: FormeFont[];\n warnings: string[];\n}\n\n/** Larger than any single face in use, CJK included; a guard against a runaway response, not a style rule. */\nconst MAX_FONT_BYTES = 32 * 1024 * 1024;\nconst FETCH_TIMEOUT_MS = 15_000;\n/** Addresses whose resolution is kept. A long-running service meets a bounded set of brands. */\nconst MAX_CACHED = 64;\n\ntype Loaded = { src: string } | { reason: string };\n\nconst cache = new Map<string, Promise<Loaded>>();\n\n/**\n * The fonts to hand the engine: the caller's own `fonts` first, exactly as given,\n * then every face in the theme the engine can read.\n *\n * The first entry for a family, weight and style wins, so an explicit font — or a\n * service's own — is never displaced by a theme naming the same face.\n */\nexport async function resolveFonts(input: { fonts?: FormeFont[]; theme?: Partial<Theme>; sources?: FontSourcePolicy }): Promise<ResolvedFonts> {\n const fonts: FormeFont[] = [];\n const warnings: string[] = [];\n const seen = new Set<string>();\n const add = (font: FormeFont) => {\n const weight = font.weight ?? 400;\n const style = font.style ?? \"normal\";\n const key = `${font.family.trim().toLowerCase()}|${weight}|${style}`;\n if (seen.has(key)) return;\n seen.add(key);\n fonts.push({ family: font.family, src: font.src, weight, style });\n };\n\n for (const font of input.fonts ?? []) add(font);\n const faces = await Promise.all((input.theme?.fonts ?? []).map((face) => themeFace(face, input.sources ?? {})));\n for (const face of faces) {\n warnings.push(...face.warnings);\n if (face.font) add(face.font);\n }\n return { fonts, warnings };\n}\n\nasync function themeFace(face: ThemeFontFace, policy: FontSourcePolicy): Promise<{ font?: FormeFont; warnings: string[] }> {\n const { weight, range } = weightOf(face.weight);\n const style = face.style === \"italic\" ? \"italic\" : \"normal\";\n const name = `\"${face.family}\" (${weight}${style === \"italic\" ? \" italic\" : \"\"})`;\n const sources = (Array.isArray(face.src) ? face.src : [face.src]).filter((s): s is string => typeof s === \"string\" && s.trim() !== \"\");\n\n const reasons: string[] = [];\n for (const src of sources) {\n const loaded = await load(src.trim(), policy);\n if (\"reason\" in loaded) {\n reasons.push(loaded.reason);\n continue;\n }\n const warnings = range\n ? [`The font \"${face.family}\" declares the weights ${String(face.weight)} from one file; the PDF engine is given it at ${weight} only. Declare a file per weight for the others to be embedded.`]\n : [];\n return { font: { family: face.family, src: loaded.src, weight, style }, warnings };\n }\n return {\n warnings: [\n `The font ${name} has no TrueType or OpenType source the PDF engine can read, so the PDF draws that text in a standard face and breaks its lines differently from the screen. ` +\n `Add a .ttf or .otf to its src${reasons.length ? ` (${reasons.join(\"; \")})` : \"\"}.`\n ]\n };\n}\n\n/** A CSS font-weight, as the single number the engine takes. A range is a variable font. */\nfunction weightOf(value: ThemeFontFace[\"weight\"]): { weight: number; range: boolean } {\n if (typeof value === \"number\" && Number.isFinite(value)) return { weight: Math.round(value), range: false };\n const text = String(value ?? \"\").trim().toLowerCase();\n if (text === \"bold\") return { weight: 700, range: false };\n const numbers = text.split(/\\s+/).map(Number).filter((n) => Number.isFinite(n) && n > 0);\n if (!numbers.length) return { weight: 400, range: false };\n return { weight: Math.round(numbers[0]!), range: numbers.length > 1 && numbers[1] !== numbers[0] };\n}\n\nasync function load(src: string, policy: FontSourcePolicy): Promise<Loaded> {\n // By name, before anything is fetched: a face's WOFF2 is for the browser beside it.\n if (/^data:(font|application)\\/(x-)?woff2?[;,]/i.test(src) || /\\.woff2?([?#]|$)/i.test(src.startsWith(\"data:\") ? \"\" : src)) {\n return { reason: `${describe(src)} is WOFF, which only a browser reads` };\n }\n\n if (src.startsWith(\"data:\")) return fromDataUri(src);\n\n const remote = /^https?:\\/\\//i.test(src);\n if (remote) {\n let host: string;\n try {\n host = new URL(src).hostname;\n } catch {\n return { reason: `${describe(src)} is not a valid address` };\n }\n const allowed = policy.allowedHosts;\n if (allowed && !allowed.includes(\"*\") && !allowed.includes(host)) return { reason: `${host} is not an allowed host` };\n } else if (policy.local === false) {\n return { reason: `${describe(src)} is neither a data: URI nor a web address, and files are not read here` };\n } else if (!localReader) {\n // No entry point installed a reader — a caller importing the module directly.\n // The engine resolves such a source itself, which is what it did before.\n return { src };\n }\n\n const key = src;\n const hit = cache.get(key);\n if (hit) return hit;\n const pending = (async (): Promise<Loaded> => {\n const bytes = remote ? await download(src, Boolean(policy.allowedHosts && !policy.allowedHosts.includes(\"*\"))) : await localReader!(src);\n if (bytes.byteLength > MAX_FONT_BYTES) return { reason: `${describe(src)} is larger than ${MAX_FONT_BYTES / 1024 / 1024} MB` };\n const problem = notEmbeddable(bytes, src);\n return problem ? { reason: problem } : { src: `data:font/ttf;base64,${toBase64(bytes)}` };\n })().catch((e: unknown) => {\n // A failure is not kept: the next render tries again rather than failing for the\n // life of the process.\n cache.delete(key);\n return { reason: `${describe(src)} could not be read (${(e as Error).message || String(e)})` };\n });\n cache.set(key, pending);\n while (cache.size > MAX_CACHED) cache.delete(cache.keys().next().value!);\n return pending;\n}\n\nasync function download(src: string, restricted: boolean): Promise<Uint8Array> {\n const signal = typeof AbortSignal !== \"undefined\" && \"timeout\" in AbortSignal ? AbortSignal.timeout(FETCH_TIMEOUT_MS) : undefined;\n // A redirect would take a restricted fetch to a host nobody checked.\n const response = await fetch(src, { redirect: restricted ? \"error\" : \"follow\", ...(signal ? { signal } : {}) });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const length = Number(response.headers.get(\"content-length\"));\n if (length > MAX_FONT_BYTES) throw new Error(`larger than ${MAX_FONT_BYTES / 1024 / 1024} MB`);\n return new Uint8Array(await response.arrayBuffer());\n}\n\nfunction fromDataUri(src: string): Loaded {\n const match = /^data:([^,]*),(.*)$/s.exec(src);\n if (!match) return { reason: \"a data: URI with no data\" };\n const base64 = /;base64$/i.test(match[1]!);\n let head: Uint8Array;\n try {\n head = base64 ? fromBase64(match[2]!.slice(0, 8)) : Uint8Array.from(decodeURIComponent(match[2]!.slice(0, 64)), (c) => c.charCodeAt(0) & 0xff);\n } catch {\n return { reason: \"a data: URI that does not decode\" };\n }\n const problem = notEmbeddable(head, \"a data: URI\");\n if (problem) return { reason: problem };\n if (base64) return { src };\n // The engine only takes the base64 form.\n const bytes = Uint8Array.from(decodeURIComponent(match[2]!), (c) => c.charCodeAt(0) & 0xff);\n return { src: `data:font/ttf;base64,${toBase64(bytes)}` };\n}\n\n/** Null when these are TrueType or OpenType bytes, otherwise why not. */\nfunction notEmbeddable(bytes: Uint8Array, src: string): string | null {\n if (bytes.length < 4) return `${describe(src)} is not a font file`;\n const tag = String.fromCharCode(bytes[0]!, bytes[1]!, bytes[2]!, bytes[3]!);\n if ((bytes[0] === 0 && bytes[1] === 1 && bytes[2] === 0 && bytes[3] === 0) || tag === \"OTTO\" || tag === \"true\") return null;\n if (tag === \"wOFF\" || tag === \"wOF2\") return `${describe(src)} is WOFF, which only a browser reads`;\n if (tag === \"ttcf\") return `${describe(src)} is a font collection; give the single face instead`;\n return `${describe(src)} is not a TrueType or OpenType file`;\n}\n\nfunction describe(src: string): string {\n return src.startsWith(\"data:\") ? \"a data: URI\" : src.length > 80 ? `${src.slice(0, 77)}…` : src;\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return btoa(binary);\n}\n\nfunction fromBase64(text: string): Uint8Array {\n const clean = text.replace(/[^A-Za-z0-9+/]/g, \"\");\n const binary = atob(clean.slice(0, clean.length - (clean.length % 4)));\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\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, Theme } from \"@broadpaper/core\";\nimport { resolveFonts, type FormeFont } from \"./fonts.js\";\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 /**\n * Fonts for the engine beyond the theme's own.\n *\n * Usually unnecessary: the faces in `theme.fonts` are read and given to the\n * engine without being named here. May be a promise, because a browser host has\n * to fetch the files and `createMeasurer` has to return synchronously. Every\n * measurement waits for it, so nothing is ever measured — and cached — with the\n * engine's standard faces standing in for a font that was still arriving.\n */\n fonts?: unknown[] | Promise<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, faces: string): string {\n return hash(JSON.stringify(section)) + \":\" + Math.round(width * 100) + \":\" + mode + \":\" + faces;\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 // A section measured in one theme's fonts is a different height in another's.\n const faces = facesKey(opts.theme.fonts);\n for (const section of sections) {\n const k = this.key(section, width, opts.mode, faces);\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 const given = await this.config.fonts;\n const { fonts, warnings } = await resolveFonts({ fonts: given as FormeFont[] | undefined, theme: opts.theme });\n for (const w of warnings) this.warn(w);\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,\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) this.warn(w);\n return out;\n }\n\n private warn(message: string): void {\n if (this.seen.has(message)) return;\n this.seen.add(message);\n this.config.onWarning?.(message);\n }\n}\n\n/** Which faces a theme declares, cheaply: a data: URI can be megabytes, so only its ends are read. */\nfunction facesKey(faces: Theme[\"fonts\"]): string {\n if (!faces?.length) return \"\";\n return hash(\n faces\n .map((f) => [f.family, f.weight, f.style, ...(Array.isArray(f.src) ? f.src : [f.src]).map((s) => `${s.length}:${s.slice(0, 64)}${s.slice(-64)}`)].join(\"|\"))\n .join(\";\")\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, type WatermarkSpec } from \"@broadpaper/license\";\nimport { vnodeToForme, type FormeNode, type TranslateContext } from \"./vnode.js\";\nimport { watermarkNode } from \"./watermark.js\";\nimport { creditNode } from \"./credit.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\nimport { resolveFonts, type FontSourcePolicy, type FormeFont } from \"./fonts.js\";\nexport { resolveFonts, setFontFileReader } from \"./fonts.js\";\nexport type { FontFileReader, FontSourcePolicy, FormeFont, ResolvedFonts } from \"./fonts.js\";\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 /**\n * Fonts handed to the engine as they are, before the theme's.\n *\n * Most hosts need none: every face in `theme.fonts` with a TrueType or OpenType\n * source is embedded without being named twice. This is for a font the theme\n * does not declare — one a service embeds in every render, say.\n */\n fonts?: FormeFont[];\n /** Where the theme's fonts may be read from. Unset, anywhere: a host's own theme is trusted. */\n fontSources?: FontSourcePolicy;\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 * An extra mark to draw behind every page, on top of whatever the licence\n * decides.\n *\n * Additive and never a replacement: the licence mark is decided by\n * `watermarkFor` and this cannot remove it, which is the property that keeps\n * \"a caller cannot reach a PDF without passing the licence check\" true. It\n * exists for a host whose own commercial model wants a mark — BroadPaper Cloud\n * marks the documents its free plan produces — and for the ordinary \"DRAFT\"\n * stamp a business document sometimes needs.\n *\n * Remember that an unstyled Forme watermark draws solid black at full opacity;\n * a spec without a colour and an opacity makes the document unreadable.\n */\n watermark?: WatermarkSpec | null;\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 // The licence mark first, then anything the caller added. The caller cannot\n // replace the first one, only sit beside it.\n const marks = [watermarkFor(license), opts.watermark].filter((m): m is WatermarkSpec => Boolean(m));\n for (const mark of marks) if ((mark.placement ?? \"center\") === \"center\") 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 /*\n * A credit line goes in the footer region on this path, not in the margin.\n *\n * The paginated path draws it in the bottom margin, where it costs no layout.\n * Here pagination belongs to the engine — this is one wrapping Page node — so\n * there is nothing to position against and no page count to repeat over, and\n * the only primitives that recur on every page are the watermark node and the\n * Fixed regions. A footer line is the honest one of the two: a `bottom`\n * placement exists precisely because a stamp in the middle of the page was\n * wrong, and degrading it back to that would be answering the wrong question.\n */\n const credits = marks\n .filter((m) => (m.placement ?? \"center\") === \"bottom\")\n .map((m) => creditNode(m, geom.contentWidth, ctx))\n .filter((n): n is FormeNode => Boolean(n));\n if (footer.length || credits.length) {\n children.push({ kind: { type: \"Fixed\", position: \"Footer\" }, style: {}, children: [...footer, ...credits] });\n }\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 const fonts = await resolveFonts({ fonts: opts.fonts, theme, sources: opts.fontSources });\n if (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 warnings = [...ctx.warnings, ...resolved.warnings.map((w) => w.message), ...fonts.warnings];\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, type SectionGeometry, type VNode } from \"@broadpaper/core\";\nimport { translate } from \"./vnode.js\";\nimport { longTables, sliceTables, stitchTables, type LongTable } from \"./long-tables.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: LayoutPaginatedOptions): Promise<RenderPaginatedResult> {\n const started = Date.now();\n const layout = await layoutPaginated(opts);\n const drawn = await layout.draw();\n return {\n pdf: drawn.pdf,\n pages: drawn.pages,\n layout: drawn.layout,\n paged: layout.paged,\n geometry: layout.geometry,\n warnings: drawn.warnings,\n durationMs: Date.now() - started\n };\n}\n\n/** A table longer than this many body rows is measured a batch at a time. */\nexport const MEASURE_BATCH_ROWS = 1_000;\n\nexport interface LayoutPaginatedOptions extends RenderFormePdfOptions {\n /**\n * Body rows per measuring pass for a long table. Only a test should change it:\n * a small number exercises the batching on a table short enough to compare with\n * measuring it whole.\n */\n measureBatchRows?: number;\n}\n\n/** A document laid out and paginated, and not yet drawn. */\nexport interface PaginatedLayout {\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 * Draws pages `[from, to)` — the whole document when no range is given — as one\n * PDF. Pages keep their numbers in the whole document, so page 251 of a split\n * document still says \"251 of 1,300\".\n */\n draw(range?: { from: number; to: number }): Promise<{ pdf: Uint8Array; pages: number; layout: { pages: FormePageInfo[] } | null; warnings: string[] }>;\n}\n\n/**\n * Resolves, measures and paginates without drawing.\n *\n * Separate from drawing for two reasons a long document made plain. The page\n * count is known here, before the more expensive half of the work, so a caller\n * with a ceiling can refuse or split first rather than after; and a document of\n * a thousand pages can be drawn as several files from one layout, every one of\n * them agreeing about where the page breaks fall and what the totals are.\n */\nexport async function layoutPaginated(opts: LayoutPaginatedOptions): Promise<PaginatedLayout> {\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 // Once, for every pass: measuring and drawing must be given the same faces, or the\n // second re-breaks what the first measured.\n const fonts = await resolveFonts({ fonts: opts.fonts, theme, sources: opts.fontSources });\n\n /** Lays these trees out on one unbounded page and reads their geometry back. */\n const layoutSections = async (list: Array<{ section: ResolvedNode; tree: VNode }>): Promise<GeometryMap> => {\n if (!list.length) return {};\n const measured: MeasuredSection[] = [];\n for (const { section, tree } of list) {\n const t = translate(tree, 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 (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 /*\n * Measures sections, with any table too long for one pass measured a batch of\n * rows at a time — see `long-tables.ts` for why one pass is wrong past about ten\n * thousand rows, not merely slow.\n */\n const batchRows = Math.max(1, opts.measureBatchRows ?? MEASURE_BATCH_ROWS);\n const measure = async (sections: ResolvedNode[]): Promise<GeometryMap> => {\n const parts: Array<{ section: ResolvedNode; tree: VNode; long: LongTable[] }> = [];\n for (const section of sections) {\n const tree = renderNode(section, renderOpts, geom.contentWidth);\n if (tree) parts.push({ section, tree, long: longTables(tree, batchRows) });\n }\n const out = await layoutSections(parts.map((p) => ({ section: p.section, tree: p.long.length ? sliceTables(p.tree, p.long, 0, batchRows) : p.tree })));\n\n for (const p of parts) {\n const first = out[p.section.key];\n if (!p.long.length || !first) continue;\n const most = Math.max(...p.long.map((t) => t.bodyRows));\n const batches: Array<{ section: ResolvedNode; tree: VNode }> = [];\n for (let start = batchRows; start < most; start += batchRows) {\n // A key of its own per batch, so several batches can share one pass.\n batches.push({ section: { ...p.section, key: `${p.section.key}#rows-${start}` }, tree: sliceTables(p.tree, p.long, start, batchRows) });\n }\n const measured: SectionGeometry[] = [];\n for (let i = 0; i < batches.length; i += BATCHES_PER_PASS) {\n const chunk = batches.slice(i, i + BATCHES_PER_PASS);\n const got = await layoutSections(chunk);\n for (const b of chunk) {\n const g = got[b.section.key];\n if (g) measured.push(g);\n }\n }\n out[p.section.key] = stitchTables(first, p.long, measured);\n }\n return out;\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 const background = template.page.background ? resolveValue(template.page.background, theme, \"#ffffff\") : undefined;\n\n return {\n paged,\n geometry,\n async draw(range) {\n const from = Math.max(0, range?.from ?? 0);\n const to = Math.min(paged.pages.length, range?.to ?? paged.pages.length);\n const pages = emitPages({\n resolved,\n // `totalPages` stays the whole document's, so a later file still counts\n // its pages as part of the whole.\n paged: { ...paged, pages: paged.pages.slice(from, to) },\n page: geom,\n renderOpts,\n ctx,\n geometry,\n background,\n watermarks: [watermarkFor(license), opts.watermark]\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 (fonts.fonts.length) doc.fonts = fontEntries(fonts.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 ?? to - from,\n layout,\n warnings: [...ctx.warnings, ...resolved.warnings.map((w) => w.message), ...paged.warnings.map((w) => w.message), ...fonts.warnings, ...(result.warnings ?? [])]\n };\n }\n };\n}\n\n/**\n * Batches laid out together in one engine pass. Two thousand ordinary rows is\n * well inside the measuring page's height; a table whose rows are each many\n * lines tall is the case that would need fewer.\n */\nconst BATCHES_PER_PASS = 2;\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 * A credit line: an optional small mark, then the text.\n *\n * `WatermarkSpec` with `placement: \"bottom\"` — the shape a host's own commercial\n * model usually wants, as distinct from the evaluation mark's diagonal stamp.\n * BroadPaper Cloud's free plan started as a `center` mark at eight points, which\n * is a small grey sentence floating in the middle of an otherwise finished\n * invoice: it reads as a mistake rather than as a credit, and the point of that\n * mark is that a free user's document stays sendable.\n *\n * Built as a VNode and put through the ordinary translator rather than assembled\n * as engine nodes by hand, which buys two things that are easy to get wrong: the\n * mark's SVG data URI is decoded and re-emitted as vector drawing — the engine's\n * image decoder cannot read an SVG and leaves a grey box where the logo should\n * be — and the sizing lands in the style box as well as in the node, which an SVG\n * needs or it is laid out as auto and takes whatever room is going.\n *\n * The text carries its own colour and size explicitly. This is a flex container,\n * so it translates to a View, and text styles do not inherit through a View.\n *\n * Both render paths use this: the paginated one draws it in the bottom margin,\n * where it costs no layout, and the engine-paginated one puts it in the Fixed\n * footer region, which is the only thing that recurs per page there.\n */\nimport type { VNode } from \"@broadpaper/core\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\nimport { translate, type FormeNode, type TranslateContext } from \"./vnode.js\";\n\nexport function creditNode(spec: WatermarkSpec, width: number, ctx: TranslateContext): FormeNode | null {\n const size = spec.fontSize;\n const children: VNode[] = [];\n\n if (spec.mark) {\n children.push({\n tag: \"img\",\n props: { src: spec.mark, alt: \"\", style: { width: `${size}px`, height: `${size}px`, opacity: String(spec.opacity) } },\n children: []\n });\n }\n\n children.push({\n tag: \"span\",\n props: { style: { \"font-size\": `${size}px`, color: spec.color, opacity: String(spec.opacity), \"line-height\": \"1.2\" } },\n children: [spec.text]\n });\n\n const line: VNode = {\n tag: \"div\",\n props: {\n style: {\n display: \"flex\",\n \"align-items\": \"center\",\n gap: `${Math.max(2, Math.round(size * 0.5))}px`,\n width: `${width}px`,\n \"justify-content\": \"center\"\n }\n },\n children\n };\n\n return translate(line, ctx)?.node ?? null;\n}\n","/**\n * Measuring a long table a batch of rows at a time.\n *\n * The measuring pass lays a section out on one page `UNBOUNDED_PAGE_HEIGHT`\n * points tall and reads the geometry back. That page is not unbounded: at twenty\n * points a row, a table of ten thousand rows is taller than it, and the engine\n * truncates anything taller than the page it is drawn on — so the paginator was\n * handed a table that ended where the page did, and twelve thousand rows came out\n * as a one-page PDF with no warning. The engine's layout time also grows faster\n * than the number of rows on one page, so one enormous pass was the slowest way to\n * measure even before it was wrong.\n *\n * So a section holding a table longer than a batch is measured several times:\n * once with every long table cut to its first batch of body rows, which places\n * everything else in the section, and once per further batch. The rows are then\n * joined back into one table's geometry and everything below the table moved down\n * by the height the extra rows take.\n *\n * Row heights do not depend on the rows around them — widths come from the\n * column definitions and the table's own width, which every pass shares — which\n * is what makes measuring them apart the same as measuring them together.\n */\nimport type { NodeGeometry, SectionGeometry, TableRowGeometry, VNode } from \"@broadpaper/core\";\n\n/** A table in a rendered section with more body rows than one pass takes. */\nexport interface LongTable {\n table: VNode;\n /** The nearest keyed node holding the table, which is where its rows are measured. */\n key: string;\n bodyRows: number;\n}\n\nconst EPS = 0.5;\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction isRow(c: VNode | string): c is VNode {\n return typeof c !== \"string\" && c.tag === \"tr\";\n}\n\n/** Body rows, counted the way the translator assigns them: `tbody` rows and bare rows. */\nfunction bodyRowCount(table: VNode): number {\n let n = 0;\n for (const c of table.children) {\n if (typeof c === \"string\") continue;\n if (c.tag === \"tbody\") n += c.children.filter(isRow).length;\n else if (c.tag === \"tr\") n++;\n }\n return n;\n}\n\n/** Every table under `tree` with more than `limit` body rows, and the key its rows are measured under. */\nexport function longTables(tree: VNode, limit: number): LongTable[] {\n const out: LongTable[] = [];\n const visit = (v: VNode, key: string | undefined) => {\n const own = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : key;\n if (v.tag === \"table\") {\n const rows = bodyRowCount(v);\n // A table with no keyed ancestor has no geometry to join rows into, and\n // is measured whole as it always was.\n if (rows > limit && own) out.push({ table: v, key: own, bodyRows: rows });\n return;\n }\n for (const c of v.children) if (typeof c !== \"string\") visit(c, own);\n };\n visit(tree, undefined);\n return out;\n}\n\n/** `tree` with each long table's body rows narrowed to `[start, start + count)`; header and footer rows kept. */\nexport function sliceTables(tree: VNode, tables: LongTable[], start: number, count: number): VNode {\n const targets = new Set(tables.map((t) => t.table));\n const visit = (v: VNode): VNode => {\n if (targets.has(v)) return sliceRows(v, start, count);\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = visit(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n };\n return visit(tree);\n}\n\nfunction sliceRows(table: VNode, start: number, count: number): VNode {\n let index = 0;\n const keep = () => {\n const i = index++;\n return i >= start && i < start + count;\n };\n const children: Array<VNode | string> = [];\n for (const c of table.children) {\n if (typeof c === \"string\") children.push(c);\n else if (c.tag === \"tbody\") children.push({ ...c, children: c.children.filter((r) => !isRow(r) || keep()) });\n else if (c.tag === \"tr\") {\n if (keep()) children.push(c);\n } else children.push(c);\n }\n return { ...table, children };\n}\n\nfunction sameRows(a: TableRowGeometry[] | undefined, b: TableRowGeometry[]): boolean {\n return !!a && a.length === b.length && a[0]?.top === b[0]?.top && a[a.length - 1]?.top === b[b.length - 1]?.top;\n}\n\n/**\n * The section's geometry with every long table's remaining rows joined in.\n *\n * `first` is the section measured with each long table cut to its first batch;\n * `batches` are the later batches, in order, each measured as the same section\n * with only that batch's rows. Tables are joined from the lowest up, so moving the\n * content under an upper table also moves a lower table that has already grown.\n */\nexport function stitchTables(first: SectionGeometry, tables: LongTable[], batches: SectionGeometry[]): SectionGeometry {\n const g: SectionGeometry = {\n ...first,\n nodes: Object.fromEntries(Object.entries(first.nodes).map(([k, n]) => [k, { ...n } as NodeGeometry]))\n };\n const bottomOf = (rows: TableRowGeometry[]) => Math.max(...rows.map((r) => r.top + r.height));\n const order = tables\n .map((t) => ({ t, rows: first.nodes[t.key]?.rows }))\n .filter((x): x is { t: LongTable; rows: TableRowGeometry[] } => !!x.rows && x.rows.some((r) => r.kind === \"body\"))\n .sort((a, b) => bottomOf(b.rows) - bottomOf(a.rows));\n\n for (const { t } of order) {\n const main = g.nodes[t.key]!.rows!;\n const body = main.filter((r) => r.kind === \"body\");\n const last = body[body.length - 1]!;\n const bodyEnd = last.top + last.height;\n // Whatever separates one row from the next — border spacing, usually nothing —\n // separates the batches too.\n const gap = body.length > 1 ? Math.max(0, body[1]!.top - (body[0]!.top + body[0]!.height)) : 0;\n\n const extra: TableRowGeometry[] = [];\n let cursor = bodyEnd + gap;\n for (const batch of batches) {\n const rows = batch.nodes[t.key]?.rows?.filter((r) => r.kind === \"body\") ?? [];\n if (!rows.length) continue;\n const base = rows[0]!.top;\n for (const r of rows) extra.push({ top: round(cursor + r.top - base), height: r.height, kind: \"body\" });\n const end = rows[rows.length - 1]!;\n cursor += end.top + end.height - base + gap;\n }\n if (!extra.length) continue;\n\n const tail = extra[extra.length - 1]!;\n const delta = round(tail.top + tail.height - bodyEnd);\n const merged: TableRowGeometry[] = [\n ...main.filter((r) => r.kind === \"header\"),\n ...body,\n ...extra,\n ...main.filter((r) => r.kind === \"footer\").map((r) => ({ ...r, top: round(r.top + delta) }))\n ];\n\n for (const n of Object.values(g.nodes)) {\n // Every keyed wrapper of the table carries its rows, because the translator\n // lifts row roles onto the nearest keyed node and each ancestor adopts them.\n const holdsThisTable = sameRows(n.rows, main);\n if (n.top >= bodyEnd - EPS) {\n n.top = round(n.top + delta);\n if (n.lines) n.lines = n.lines.map((y) => round(y + delta));\n if (n.rows && !holdsThisTable) n.rows = n.rows.map((r) => ({ ...r, top: round(r.top + delta) }));\n } else if (n.top + n.height > bodyEnd - EPS) {\n n.height = round(n.height + delta);\n }\n if (holdsThisTable) n.rows = merged;\n }\n g.height = round(g.height + delta);\n }\n return g;\n}\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 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 { creditNode } from \"./credit.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/**\n * Strips a rendered table down to its header rows, for repeating across pages.\n *\n * Copies only the path down to each table rather than cloning the tree: a deep\n * clone of a fifty-thousand-row table to keep its one header row was most of the\n * cost of a long document. Nothing downstream mutates a VNode, so the untouched\n * branches are shared.\n */\nfunction headerOnly(v: VNode): VNode {\n if (v.tag === \"table\") {\n return { ...v, children: v.children.filter((c) => typeof c !== \"string\" && (c.tag === \"colgroup\" || c.tag === \"thead\")) };\n }\n let changed = false;\n const children = v.children.map((c) => {\n if (typeof c === \"string\") return c;\n const next = headerOnly(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\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 * Marks to draw behind the content, in order.\n *\n * A list rather than one, because two separate decisions can each ask for a\n * mark and neither may cancel the other: the licence decides whether the\n * output carries the evaluation mark, and a host — BroadPaper Cloud is the\n * first — may add one of its own for its own commercial reasons. Collapsing\n * them into a single slot is how the licence mark eventually gets overwritten\n * by somebody who only meant to add a \"DRAFT\".\n *\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 watermarks?: Array<WatermarkSpec | null | undefined>;\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 /*\n * The section's tree, rendered once and cropped once per page.\n *\n * Rendering it again for every window made a long table quadratic: each of a\n * hundred pages re-rendered all four thousand rows only for the crop to throw\n * all but forty away, and at fifty thousand rows that step alone ran for tens of\n * minutes. `cropToWindow` never mutates its input, so one tree serves every page\n * — unless the body reads `page.*`, where each page needs its own.\n */\n const rendered = new Map<string, VNode | null>();\n const treeOf = (section: ResolvedNode, opts: RenderTreeOptions): VNode | null => {\n if (bodyDependsOnPage) return renderNode(section, opts, width);\n if (!rendered.has(section.key)) rendered.set(section.key, renderNode(section, opts, width));\n return rendered.get(section.key)!;\n };\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 = treeOf(section, opts);\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 /*\n * A table's repeated header, drawn once per table and reused on every page.\n *\n * It used to render the whole table afresh on every continuation page and copy\n * all of it to keep the header rows — at two thousand rows that was four seconds\n * of a twenty-second render, and it grew with rows times pages.\n */\n const headers = new Map<string, FormeNode | null>();\n const repeatedHeader = (tableKey: string, table: ResolvedNode, opts: RenderTreeOptions, headerWidth: number): FormeNode | null => {\n const key = `${tableKey}|${headerWidth}`;\n if (!bodyDependsOnPage && headers.has(key)) return headers.get(key)!;\n const v = renderNode(table, opts, headerWidth);\n const t = v ? translate(headerOnly(v), ctx) : null;\n const node = t ? t.node : null;\n if (!bodyDependsOnPage) headers.set(key, node);\n return node;\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 marks are under the report and not across it.\n for (const mark of input.watermarks ?? []) if (mark && (mark.placement ?? \"center\") === \"center\") children.push(watermarkNode(mark));\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 header = repeatedHeader(r.tableKey, table, opts, r.width);\n if (header) inner.push(box(r.left, 0, r.width, r.height, [header]));\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 /*\n * A credit line along the foot of the page.\n *\n * In the bottom margin rather than in the footer band, and that is the whole\n * reason it is here and not injected into the template: a mark that took\n * content height would make the finished file paginate differently from the\n * canvas the user approved, and the margin is the one part of the page nothing\n * else lays out in.\n *\n * After the content, unlike the diagonal stamp, because it sits in a margin\n * where there is nothing to be under.\n */\n for (const mark of input.watermarks ?? []) {\n if (!mark || (mark.placement ?? \"center\") !== \"bottom\") continue;\n const node = creditNode(mark, width, ctx);\n if (!node) continue;\n const h = mark.fontSize * 1.6;\n // Centred in the bottom margin, or sitting on the page edge when the margin\n // is too shallow to centre anything in.\n const top = Math.max(page.height - h, page.height - page.margins.bottom + Math.max(0, (page.margins.bottom - h) / 2));\n children.push(box(page.margins.left, top, width, h, [node]));\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 * - The run of blocks wholly above the window, at the start of a stack of\n * siblings, is removed. The first block that stays moves up to where the first\n * removed one began — a distance the geometry gives exactly, gaps and all — and\n * that distance is added to `offset`.\n * - Any other node wholly outside the window becomes an empty box of exactly the\n * height 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 — added to the same `offset`,\n * so the page can take it off the shift it was going to apply.\n *\n * The removal is not tidiness. Keeping full-height boxes above the window made a\n * section's third page a node three pages tall with the page's content at the\n * bottom of it, and the engine's truncation then moved that content up and\n * dropped the first blocks it held — an imported invoice lost a heading and six\n * table rows from its second page, with no warning. Emptying the boxes to zero\n * height is not enough either: a stack's `gap` survives between empty boxes, and\n * a hundred of them still push the page's content past the page. Only stacks are\n * trimmed: in columns side by side, removing one column's blocks would move that\n * column and not its neighbour, and there is no single offset to report.\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, true);\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\n/**\n * @param stacked whether `v` and everything above it up to the section sit in a\n * single column, so that removing height from `v` moves everything after it by\n * exactly that much.\n */\nfunction crop(v: VNode, w: Window, rows: TableRowGeometry[] | undefined, stacked: boolean): VNode {\n const g = geometryOf(v, w.geom);\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 const childrenStacked = stacked && !sideBySide(v.children, w.geom);\n const removed = childrenStacked ? removeAbove(v.children, w) : 0;\n let changed = removed > 0;\n const children = v.children.slice(removed).map((c) => {\n if (typeof c === \"string\") return c;\n const next = crop(c, w, rows, childrenStacked);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...v, children } : v;\n}\n\nfunction geometryOf(v: VNode, geom: SectionGeometry): SectionGeometry[\"nodes\"][string] | undefined {\n const key = typeof v.props[\"data-key\"] === \"string\" ? (v.props[\"data-key\"] as string) : undefined;\n return key ? geom.nodes[key] : undefined;\n}\n\n/** The vertical span a node's measured content covers, looking through unmeasured wrappers. */\nfunction extent(v: VNode, geom: SectionGeometry): [number, number] | null {\n const g = geometryOf(v, geom);\n if (g) return g.height > EPS ? [g.top, g.top + g.height] : null;\n let span: [number, number] | null = null;\n for (const c of v.children) {\n if (typeof c === \"string\") continue;\n const e = extent(c, geom);\n if (e) span = span ? [Math.min(span[0], e[0]), Math.max(span[1], e[1])] : e;\n }\n return span;\n}\n\n/** Whether any two of these siblings share a band of height — columns, not a stack. */\nfunction sideBySide(children: Array<VNode | string>, geom: SectionGeometry): boolean {\n const spans = children\n .filter((c): c is VNode => typeof c !== \"string\")\n .map((c) => extent(c, geom))\n .filter((e): e is [number, number] => e !== null)\n .sort((a, b) => a[0] - b[0]);\n let bottom = Number.NEGATIVE_INFINITY;\n for (const [top, end] of spans) {\n if (top < bottom - EPS) return true;\n bottom = Math.max(bottom, end);\n }\n return false;\n}\n\n/**\n * How many leading children of a stack lie wholly above the window, having added\n * the height their removal takes out to `w.dropped`.\n *\n * Measured from the geometry rather than summed from heights, because what sits\n * between the blocks — a stack's `gap`, their margins — is removed with them. The\n * first block that stays lands where the first removed one's margin box began,\n * plus its own top margin. When they are all removed, the stack closes up by the\n * whole run. A block without geometry of its own ends the run, since where it\n * would land cannot be read, and the blocks before it are left as empty boxes.\n */\nfunction removeAbove(children: Array<VNode | string>, w: Window): number {\n let start: number | null = null;\n let end = 0;\n let count = 0;\n for (let i = 0; i < children.length; i++) {\n const c = children[i]!;\n if (typeof c === \"string\") {\n if (c.trim()) return 0;\n continue;\n }\n const g = geometryOf(c, w.geom);\n if (!g) return 0;\n if (g.top + g.height > w.from + EPS) {\n if (start === null) return 0;\n w.dropped += g.top - margin(c, \"top\") - start;\n return i;\n }\n start ??= g.top - margin(c, \"top\");\n end = g.top + g.height + margin(c, \"bottom\");\n count = i + 1;\n }\n if (start === null) return 0;\n w.dropped += end - start;\n return count;\n}\n\n/** A node's top or bottom margin in pixels, from its inline style; zero for anything but pixels. */\nfunction margin(v: VNode, side: \"top\" | \"bottom\"): number {\n let value = 0;\n for (const declaration of styleString(v.props.style).split(\";\")) {\n const m = /^\\s*margin(?:-(top|bottom|left|right))?\\s*:\\s*(.+?)\\s*$/i.exec(declaration);\n if (!m) continue;\n if (m[1]) {\n if (m[1].toLowerCase() === side) value = pixels(m[2]!);\n } else {\n const parts = m[2]!.split(/\\s+/);\n value = pixels((side === \"top\" ? parts[0] : parts.length >= 3 ? parts[2] : parts[0])!);\n }\n }\n return value;\n}\n\nfunction pixels(length: string): number {\n const m = /^(-?\\d*\\.?\\d+)(px)?$/i.exec(length.trim());\n return m && (m[2] || Number(m[1]) === 0) ? Number(m[1]) : 0;\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","length","renderNode","mapStyle","resolveLicenseStatus","round","renderNode","mapStyle","styleString","EPS","length","round","mapStyle","cache","renderNode","translate","renderNode","mapStyle","scale"]}