/** The minimum `window` surface this needs — so a test can supply a fake. */ export interface PrintableWindow { document: { readyState: string; }; addEventListener: (type: string, handler: () => void, options?: { once?: boolean; }) => void; print: () => void; } export interface PrintWhenReadyOptions { /** * Settle time between highlighting and `print()`. A real browser needs a beat to lay the * tokens out; a test passes 0. */ delayMs?: number; /** Injected for tests. */ setTimeoutFn?: (fn: () => void, ms: number) => unknown; } /** * Highlight, then print — after the window has actually loaded. * * Returns a promise that resolves once `print()` has been scheduled, so a caller (or a test) * can await the decision rather than the dialog. * * A failing highlight still prints. Plain code beats a print dialog that never opens: the * reader asked for a document, and an un-highlighted one is a worse document rather than no * document. */ export declare function printWhenReady(win: PrintableWindow, highlight: () => Promise, opts?: PrintWhenReadyOptions): Promise; export interface ResolveBookCoverOptions { /** Injected for tests. */ fetchFn?: (url: string) => Promise<{ ok: boolean; json: () => Promise; }>; /** Resolves when the image at `url` loads, rejects when it does not. Injected for tests. */ loadImage?: (url: string) => Promise; /** * How long the whole lookup may take before Print goes ahead without a cover. The files * are small and same-origin, so this only bites on a stalled connection. */ timeoutMs?: number; } /** * The cover Print should open with, or `undefined` for none. * * Reads the default volume's `coverUrl` from the volume manifest the site build wrote, then * loads the image before answering. Both steps are checks on purpose: the manifest lists a * cover only when the build wrote one, and loading it here means the printed book never * starts with a broken image and a page break — without an inline `onerror`, which a * Content-Security-Policy would block in the popup. * * Any failure means no cover, and so does taking too long: the popup is already open and * blank while this runs, and a request that never settles must not leave it that way. Print * must still happen. */ export declare function resolveBookCover(manifestUrl: string | undefined, opts?: ResolveBookCoverOptions): Promise;