From 3177b2f1ebb1c414ebf06b3143865eee8f3aa217 Mon Sep 17 00:00:00 2001 From: PJ Date: Mon, 22 Jun 2026 12:01:25 -0400 Subject: [PATCH] fix(preview): show render errors instead of a blank pane The render loop swallowed getDocument/render rejections, leaving the preview silently blank with no signal about what failed. Surface the error in the pane and recover on the next compile. Also drop the redundant canvasContext arg (pdf.js v6 renders via the canvas itself). --- src/components/PdfPreview.tsx | 56 +++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/components/PdfPreview.tsx b/src/components/PdfPreview.tsx index 921d2b9..52a1b35 100644 --- a/src/components/PdfPreview.tsx +++ b/src/components/PdfPreview.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import * as pdfjs from "pdfjs-dist"; import workerUrl from "pdfjs-dist/build/pdf.worker.min.mjs?url"; @@ -6,6 +6,7 @@ pdfjs.GlobalWorkerOptions.workerSrc = workerUrl; export function PdfPreview({ data }: { data: Uint8Array }) { const ref = useRef(null); + const [error, setError] = useState(null); useEffect(() => { const container = ref.current; @@ -13,29 +14,35 @@ export function PdfPreview({ data }: { data: Uint8Array }) { let cancelled = false; (async () => { - const doc = await pdfjs.getDocument({ data: data.slice() }).promise; - if (cancelled) return; - const width = container.clientWidth; - const dpr = window.devicePixelRatio || 1; - const canvases: HTMLCanvasElement[] = []; + try { + const doc = await pdfjs.getDocument({ data: data.slice() }).promise; + if (cancelled) return; + const width = container.clientWidth; + const dpr = window.devicePixelRatio || 1; + const canvases: HTMLCanvasElement[] = []; - for (let n = 1; n <= doc.numPages; n++) { - const page = await doc.getPage(n); + for (let n = 1; n <= doc.numPages; n++) { + const page = await doc.getPage(n); + if (cancelled) return; + const base = page.getViewport({ scale: 1 }); + const scale = width / base.width; + const viewport = page.getViewport({ scale: scale * dpr }); + const canvas = document.createElement("canvas"); + canvas.className = "pdf-page"; + canvas.width = viewport.width; + canvas.height = viewport.height; + canvas.style.width = "100%"; + await page.render({ canvas, viewport }).promise; + if (cancelled) return; + canvases.push(canvas); + } + container.replaceChildren(...canvases); + setError(null); + } catch (e) { if (cancelled) return; - const base = page.getViewport({ scale: 1 }); - const scale = width / base.width; - const viewport = page.getViewport({ scale: scale * dpr }); - const canvas = document.createElement("canvas"); - canvas.className = "pdf-page"; - canvas.width = viewport.width; - canvas.height = viewport.height; - canvas.style.width = "100%"; - const context = canvas.getContext("2d")!; - await page.render({ canvas, canvasContext: context, viewport }).promise; - if (cancelled) return; - canvases.push(canvas); + container.replaceChildren(); + setError(String(e)); } - container.replaceChildren(...canvases); })(); return () => { @@ -43,5 +50,10 @@ export function PdfPreview({ data }: { data: Uint8Array }) { }; }, [data]); - return
; + return ( + <> + {error &&
{error}
} +
+ + ); }