mirror of https://github.com/buster-so/buster.git
pdf export coming soon.
This commit is contained in:
parent
edabcac7f2
commit
d3dd804a3f
|
@ -79,119 +79,7 @@ export const useExportReport = () => {
|
|||
};
|
||||
|
||||
const exportToPdf = async (editor: PlateEditor) => {
|
||||
try {
|
||||
const { default: html2canvas } = await import('html2canvas-pro');
|
||||
|
||||
const editorNode = editor.api.toDOMNode(editor);
|
||||
if (!editorNode) throw new Error('Editor not found');
|
||||
|
||||
// Clone the editor DOM to a sandbox so we can mutate it for printing
|
||||
const clonedRoot = editorNode.cloneNode(true) as HTMLElement;
|
||||
|
||||
// Sandbox: attach off-screen to compute sizes and rasterize metrics
|
||||
const sandbox = document.createElement('div');
|
||||
sandbox.setAttribute('data-report-print-sandbox', 'true');
|
||||
sandbox.style.position = 'fixed';
|
||||
sandbox.style.left = '-10000px';
|
||||
sandbox.style.top = '0';
|
||||
sandbox.style.width = '850px';
|
||||
sandbox.style.pointerEvents = 'none';
|
||||
sandbox.appendChild(clonedRoot);
|
||||
document.body.appendChild(sandbox);
|
||||
|
||||
// Ensure consistent fonts in the clone
|
||||
clonedRoot.style.fontFamily =
|
||||
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
|
||||
|
||||
// Replace metric figures with rasterized images so only charts become images in PDF
|
||||
const figureNodes = Array.from(
|
||||
clonedRoot.querySelectorAll<HTMLElement>('figure[data-metric-figure]')
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
figureNodes.map(async (figure) => {
|
||||
// Render the figure to a canvas, then replace with an image element
|
||||
const canvas = await html2canvas(figure, {
|
||||
backgroundColor: '#ffffff',
|
||||
useCORS: true
|
||||
});
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = canvas.toDataURL('image/png');
|
||||
image.style.width = `${canvas.width}px`;
|
||||
image.style.height = 'auto';
|
||||
image.setAttribute('data-exported-metric-image', 'true');
|
||||
|
||||
figure.replaceWith(image);
|
||||
})
|
||||
);
|
||||
|
||||
// Build printable HTML document
|
||||
const printWindow = window.open('', '_blank');
|
||||
if (!printWindow) throw new Error('Unable to open print window');
|
||||
|
||||
const headStyles = Array.from(document.querySelectorAll('link[rel="stylesheet"], style'))
|
||||
.map((n) => n.outerHTML)
|
||||
.join('\n');
|
||||
|
||||
const printHtml = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
${headStyles}
|
||||
<style>
|
||||
@page { size: A4; margin: 16mm; }
|
||||
html, body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
|
||||
.report-print-root { width: 850px; margin: 0 auto; }
|
||||
/* Hide interactive cursors/placeholders if any slipped in */
|
||||
[contenteditable="true"] { outline: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="report-print-root">${clonedRoot.outerHTML}</div>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(printHtml);
|
||||
printWindow.document.close();
|
||||
|
||||
// Wait for images to load in the print window before printing
|
||||
await new Promise<void>((resolve) => {
|
||||
const imgs = Array.from(printWindow.document.images);
|
||||
if (imgs.length === 0) return resolve();
|
||||
let loaded = 0;
|
||||
imgs.forEach((img) => {
|
||||
if (img.complete) {
|
||||
loaded++;
|
||||
if (loaded === imgs.length) resolve();
|
||||
} else {
|
||||
img.onload = () => {
|
||||
loaded++;
|
||||
if (loaded === imgs.length) resolve();
|
||||
};
|
||||
img.onerror = () => {
|
||||
loaded++;
|
||||
if (loaded === imgs.length) resolve();
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Cleanup sandbox
|
||||
sandbox.remove();
|
||||
|
||||
// Print. User can select "Save as PDF" to get a true text PDF with charts as images.
|
||||
printWindow.focus();
|
||||
printWindow.print();
|
||||
|
||||
openInfoMessage(NodeTypeLabels.pdfExportedSuccessfully.label);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
openErrorMessage(NodeTypeLabels.failedToExportPdf.label);
|
||||
}
|
||||
openInfoMessage('PDF export coming soon...');
|
||||
};
|
||||
|
||||
const exportToImage = async (editor: PlateEditor) => {
|
||||
|
|
Loading…
Reference in New Issue