ultisuite-client/lib/drive/docs-print.ts
R3D347HR4Y 303b2b1074
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
wow
2026-06-11 01:22:40 +02:00

85 lines
2.7 KiB
TypeScript

import type { DocPageLayout } from "@/lib/drive/doc-page-setup"
import { buildParagraphStylesCss } from "@/lib/drive/docs-paragraph-styles-css"
import type { DocParagraphStylesCatalog } from "@/lib/drive/docs-paragraph-styles"
import type { DocsExportSnapshot } from "@/lib/drive/docs-export-snapshot"
const PRINT_STYLE_ID = "docs-print-dynamic-styles"
function buildPageRule(pageLayout: DocPageLayout): string {
const wMm = pageLayout.format.widthMm
const hMm = pageLayout.format.heightMm
const landscape =
pageLayout.format.widthMm > pageLayout.format.heightMm ||
(pageLayout.format.widthMm === pageLayout.format.heightMm && false)
const size = landscape ? `${hMm}mm ${wMm}mm` : `${wMm}mm ${hMm}mm`
return `@page { size: ${size}; margin: 0; }`
}
function injectPrintStyles(
pageLayout: DocPageLayout,
paragraphStyles: DocParagraphStylesCatalog
): () => void {
const existing = document.getElementById(PRINT_STYLE_ID)
existing?.remove()
const style = document.createElement("style")
style.id = PRINT_STYLE_ID
style.textContent = [
buildPageRule(pageLayout),
buildParagraphStylesCss(paragraphStyles, ".ultidrive-richtext-editor, .ultidrive-richtext-region-editor"),
].join("\n")
document.head.appendChild(style)
return () => {
style.remove()
}
}
async function waitForPrintLayout(): Promise<void> {
if (typeof document !== "undefined" && document.fonts?.ready) {
await document.fonts.ready
}
await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
}
export type DocsPrintMode = "print" | "pdf-capture"
export async function prepareDocsPrintEnvironment(
snapshot: DocsExportSnapshot,
mode: DocsPrintMode = "print"
): Promise<() => void> {
const root = document.documentElement
root.classList.add("docs-printing")
if (mode === "pdf-capture") {
root.classList.add("docs-pdf-capture")
}
const removeStyles = injectPrintStyles(snapshot.pageLayout, snapshot.paragraphStyles)
await waitForPrintLayout()
return () => {
root.classList.remove("docs-printing", "docs-pdf-capture")
removeStyles()
}
}
export async function printDocsDocument(snapshot: DocsExportSnapshot): Promise<void> {
const cleanup = await prepareDocsPrintEnvironment(snapshot, "print")
const onAfterPrint = () => {
cleanup()
window.removeEventListener("afterprint", onAfterPrint)
}
window.addEventListener("afterprint", onAfterPrint)
window.print()
// Fallback cleanup if afterprint never fires (some browsers)
window.setTimeout(() => {
if (document.documentElement.classList.contains("docs-printing")) {
cleanup()
}
}, 2000)
}