fix(document): configure pdf.js wasmUrl so CCITT/JBIG2 scans stop rendering blank (#708) #713

Merged
marcel merged 15 commits from feat/issue-708-pdfjs-wasmurl into main 2026-06-01 21:25:57 +02:00
3 changed files with 52 additions and 0 deletions
Showing only changes of commit e8e57d2712 - Show all commits

View File

@@ -0,0 +1,52 @@
import { describe, it, expect, afterEach, vi } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import PdfViewer from './PdfViewer.svelte';
import ccittUrl from './fixtures/ccitt-g4.pdf?url';
import jpegUrl from './fixtures/jpeg-dct.pdf?url';
// Behavioral, real-render coverage of the wasm decode path. Unlike the rest of
// the viewer tests, these use the REAL pdf.js loader (no libLoader prop) so the
// page is actually decoded and painted, and the wasm is fetched from
// /pdfjs-wasm/ exactly as in production. CI runs this in a real Chromium.
// See issue #708.
afterEach(cleanup);
// A blank page is a uniform white canvas. A rendered page has dark glyph pixels.
function countNonBackgroundPixels(canvas: HTMLCanvasElement): number {
const ctx = canvas.getContext('2d');
if (!ctx || canvas.width === 0 || canvas.height === 0) return 0;
const { data } = ctx.getImageData(0, 0, canvas.width, canvas.height);
let count = 0;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
if (a > 0 && (r < 250 || g < 250 || b < 250)) count++;
}
return count;
}
async function expectNonBlankRender(url: string): Promise<void> {
render(PdfViewer, { url, documentId: 'fixture' });
await vi.waitFor(
() => {
const canvas = document.querySelector('canvas');
expect(canvas).not.toBeNull();
expect((canvas as HTMLCanvasElement).width).toBeGreaterThan(0);
expect(countNonBackgroundPixels(canvas as HTMLCanvasElement)).toBeGreaterThan(50);
},
{ timeout: 20000, interval: 250 }
);
}
describe('PdfViewer — real codec fixtures (wasm decode path)', () => {
it('renders a CCITT (G4 fax) scan as a non-blank page — same jbig2.wasm path JBIG2 uses', async () => {
await expectNonBlankRender(ccittUrl);
});
it('renders a DCTDecode (JPEG) PDF as a non-blank page — no regression', async () => {
await expectNonBlankRender(jpegUrl);
});
});

Binary file not shown.

Binary file not shown.