// Pure mapping from the public PDFRenderer options to the underlying // Playwright `page.pdf()` options. Kept side-effect free and browser-free so it // can be unit-tested without launching Chromium. import type { PageMargin, PaperSize } from "./print-css"; export interface PDFRenderOptions { /** Paper size. Defaults to "Letter". */ paperSize?: PaperSize; /** * Page margin. A single CSS length applies to all sides; an object sets * sides individually (missing sides default to "0"). Defaults to "0.5in". */ margin?: PageMargin; /** * Whether to print CSS backgrounds (colors/images). Defaults to `true` — * invoices and reports rely on background fills for headers/zebra rows. */ printBackground?: boolean; } /** Per-side margin object as Playwright's `page.pdf()` expects it. */ export interface PlaywrightMargin { top: string; right: string; bottom: string; left: string; } /** Subset of Playwright's PDFOptions this module produces. */ export interface PlaywrightPdfOptions { format: "Letter" | "A4"; margin: PlaywrightMargin; printBackground: boolean; /** * When true, a template's own `@page` size/margin wins over `format`/`margin`. * Always enabled so the shared print-CSS base remains authoritative while the * options provide a sane fallback for HTML that omits an `@page` rule. */ preferCSSPageSize: true; } const DEFAULT_MARGIN = "0.5in"; export function resolveMargin( margin: PageMargin | undefined, ): PlaywrightMargin { if (margin === undefined) { return { top: DEFAULT_MARGIN, right: DEFAULT_MARGIN, bottom: DEFAULT_MARGIN, left: DEFAULT_MARGIN, }; } if (typeof margin === "string") { return { top: margin, right: margin, bottom: margin, left: margin }; } return { top: margin.top ?? "0", right: margin.right ?? "0", bottom: margin.bottom ?? "0", left: margin.left ?? "0", }; } /** * Translate public render options into Playwright `page.pdf()` options. Pure: * no browser, no I/O. */ export function toPdfOptions( options: PDFRenderOptions = {}, ): PlaywrightPdfOptions { return { format: options.paperSize === "A4" ? "A4" : "Letter", margin: resolveMargin(options.margin), printBackground: options.printBackground ?? true, preferCSSPageSize: true, }; }