import type { DocPageSetup } from "./doc-page-setup.ts" import { DOCS_PAGE_GAP_PX } from "./docs-page-layout-constants.ts" import { mmToPx } from "./doc-page-setup.ts" export type DocsPageMetrics = { pageWidth: number pageHeight: number margins: { top: number; right: number; bottom: number; left: number } headerMarginPx: number footerMarginPx: number bodyAreaHeight: number interPageSpacer: number } export function computePageMetrics(pageLayout: { widthPx: number heightPx: number marginsPx: { top: number; right: number; bottom: number; left: number } headerMarginMm?: number footerMarginMm?: number effectiveMarginsPx?: { top: number; right: number; bottom: number; left: number } }): DocsPageMetrics { const margins = pageLayout.effectiveMarginsPx ?? pageLayout.marginsPx const headerMarginPx = pageLayout.headerMarginMm != null ? mmToPx(pageLayout.headerMarginMm) : pageLayout.marginsPx.top const footerMarginPx = pageLayout.footerMarginMm != null ? mmToPx(pageLayout.footerMarginMm) : pageLayout.marginsPx.bottom const bodyAreaHeight = pageLayout.heightPx - margins.top - margins.bottom const interPageSpacer = margins.bottom + DOCS_PAGE_GAP_PX + margins.top return { pageWidth: pageLayout.widthPx, pageHeight: pageLayout.heightPx, margins, headerMarginPx, footerMarginPx, bodyAreaHeight: Math.max(1, bodyAreaHeight), interPageSpacer, } } /** Page count from prose content height (excludes outer surface padding). */ export function computePageCount(contentHeight: number, metrics: DocsPageMetrics): number { if (contentHeight <= 0) return 1 const { bodyAreaHeight, interPageSpacer } = metrics let remaining = contentHeight let pages = 1 while (remaining > bodyAreaHeight) { remaining -= bodyAreaHeight if (remaining <= 0) break remaining -= interPageSpacer pages += 1 } return pages } export function computeStackHeight(pageCount: number, pageHeight: number): number { return pageCount * pageHeight + Math.max(0, pageCount - 1) * DOCS_PAGE_GAP_PX } /** Minimum prose height to align with visual page stack including inter-page spacers. */ export function computeProseMinHeight(pageCount: number, metrics: DocsPageMetrics): number { const { bodyAreaHeight, interPageSpacer } = metrics return ( pageCount * bodyAreaHeight + Math.max(0, pageCount - 1) * interPageSpacer ) } export function emptyRegionDoc() { return { type: "doc", content: [{ type: "paragraph" }] } } export function pageSetupFromMetrics( setup: DocPageSetup | null | undefined, patch: Partial ): DocPageSetup { return { ...(setup ?? defaultMinimalSetup()), ...patch } } function defaultMinimalSetup(): DocPageSetup { return { widthMm: 210, heightMm: 297, marginsMm: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 }, } }