From 0fd7f4860b0fc8c3252de22ca2648ddb1bfdec77 Mon Sep 17 00:00:00 2001 From: Cristian Necula Date: Mon, 11 Dec 2023 03:29:19 +0200 Subject: [PATCH] fix: handle lazy images in download and print pdf --- lib/pdf.js | 57 +++++++++++++++++++++++++++---------------------- lib/print.js | 11 +++++++--- stories/data.js | 7 ++++-- 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/lib/pdf.js b/lib/pdf.js index b1b8745..b3f12ab 100644 --- a/lib/pdf.js +++ b/lib/pdf.js @@ -1,32 +1,34 @@ -export const - fit = (rect, bounds) => { +import { invoke } from '@neovici/cosmoz-utils/function'; + +export const fit = (rect, bounds) => { const rectRatio = rect.width / rect.height, boundsRatio = bounds.width / bounds.height; return rectRatio > boundsRatio ? { - width: bounds.width, - height: rect.height * (bounds.width / rect.width) - } + width: bounds.width, + height: rect.height * (bounds.width / rect.width), + } : { - width: rect.width * (bounds.height / rect.height), - height: bounds.height - }; + width: rect.width * (bounds.height / rect.height), + height: bounds.height, + }; }, - create = async (urls, credentials) => { const options = { credentials: credentials ? 'include' : 'omit' }, - [{ jsPDF }, ...responses$] = await Promise.all([import('jspdf'), ...urls.map( - async url => { + [{ jsPDF }, ...responses$] = await Promise.all([ + import('jspdf'), + ...urls.map(async (_url) => { + const url = await Promise.resolve(invoke(_url)); const response = await fetch(url, options); return response.ok ? { - url, - data: new Uint8Array(await response.arrayBuffer()) - } + url, + data: new Uint8Array(await response.arrayBuffer()), + } : undefined; - } - )]), + }), + ]), responses = responses$.filter(Boolean); if (responses.length < 1) { @@ -36,32 +38,37 @@ export const const pdf = new jsPDF(); // eslint-disable-line new-cap responses.filter(Boolean).forEach(({ url, data }, i) => { - const - padding = 2, //in mm - { internal: { pageSize }} = pdf, + const padding = 2, //in mm + { + internal: { pageSize }, + } = pdf, { width, height } = fit(pdf.getImageProperties(data), { width: pageSize.getWidth() - padding * 2, - height: pageSize.getHeight() - padding * 2 + height: pageSize.getHeight() - padding * 2, }); if (i > 0) { pdf.addPage(); } - pdf.addImage(data, url.split('.').pop().toUpperCase(), padding, padding, width, height); - + pdf.addImage( + data, + url.split('.').pop().toUpperCase(), + padding, + padding, + width, + height, + ); }); return pdf.output('blob'); }, - downloadBlob = (blob, filename) => { const url = URL.createObjectURL(blob), a = document.body.appendChild(document.createElement('a')); a.href = url; - a.download = `${ filename }.pdf`; + a.download = `${filename}.pdf`; a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }, - download = async (urls, filename, credentials) => { const blob = await create(urls, credentials); if (blob) { diff --git a/lib/print.js b/lib/print.js index 6232d83..94637db 100644 --- a/lib/print.js +++ b/lib/print.js @@ -1,4 +1,6 @@ +import { invoke } from '@neovici/cosmoz-utils/function'; import { html, render } from 'lit-html'; +import { until } from 'lit-html/directives/until.js'; const waitFor = (condition) => new Promise((resolve) => { @@ -20,14 +22,17 @@ export const print = ({ images }) => { page-break-after: always; max-height: 100%; width: 100%; - }${images.map((src) => html``)}`, + } + + ${images.map( + (src) => html``, + )}`, pout.document.body, ); waitFor(() => Array.from(pout.document.querySelectorAll('img')).every( - (img) => img.complete, + (img) => img.src && img.complete, ), ) .then(() => pout.print()) diff --git a/stories/data.js b/stories/data.js index 093fd63..a2501a0 100644 --- a/stories/data.js +++ b/stories/data.js @@ -1,6 +1,9 @@ export const images = [ 'stories/images/stockholm.jpg', 'this-is-a-loading-error.jpg', - 'stories/images/a_size.png', - 'stories/images/strasbourg.jpg', + () => 'stories/images/a_size.png', + () => + new Promise((resolve) => + setTimeout(() => resolve('stories/images/strasbourg.jpg'), 500), + ), ];