Custom PDF backend
Swap the bundled jspdf pipeline for your own renderer - or run generation in a Worker.
Editor.Root accepts a pdf prop with two optional functions: generate and estimate. Anything omitted falls back to the bundled @docmosaic/core implementation.
Why override
- Different renderer. Swap
jspdfforpdf-lib,pdfkit, orreact-pdf. - Worker offload. Move the synchronous part of generation off the main thread.
- Server-side rendering. Send the document to your backend and stream the result down.
- Testing. Mock the pipeline entirely with deterministic output.
Signatures
The two functions are typed off the core exports - copy the signatures to stay compatible:
import type { generatePDF, estimatePDFSize } from '@docmosaic/core';
const generate: typeof generatePDF = async (sections, options, onProgress) => {
// ...
};
const estimate: typeof estimatePDFSize = (sections, backgrounds) => {
// ...
};generate must honor the third argument - onProgress(value: number) reports 0 → 1 to the bundled GenerationProgress overlay. options.signal is an AbortSignal you should respect at every awaitable step.
Full example - pdf-lib + Worker
import type { generatePDF as GenerateFn } from '@docmosaic/core';
const generate: GenerateFn = async (sections, options, onProgress) => {
const worker = new Worker(new URL('./pdf-worker.ts', import.meta.url), { type: 'module' });
try {
return await new Promise<Blob>((resolve, reject) => {
worker.addEventListener('message', (e) => {
if (e.data.type === 'progress') onProgress?.(e.data.value);
if (e.data.type === 'done') resolve(e.data.blob);
if (e.data.type === 'error') reject(new Error(e.data.message));
});
worker.postMessage({ sections, options });
options.signal?.addEventListener('abort', () => {
worker.terminate();
reject(new Error('PDF generation cancelled'));
});
});
} finally {
worker.terminate();
}
};
<Editor.Root pdf={{ generate }}>{/* ... */}</Editor.Root>;Estimation
estimatePDFSize is called frequently (every time the document changes) so it must be cheap. If your custom backend can't produce a fast estimate, leave estimate undefined - Editor.FileSizeBadge will fall back to the bundled heuristic.