85 lines
2.7 KiB
TypeScript
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)
|
|
}
|