Merge pull request 'Fix imported PDFs not rendering in the Docker image' (#3) from fix-pdf-worker into main

Reviewed-on: https://git.srazka.com/reudy-net/Papure/pulls/3
This commit is contained in:
reudy 2026-09-27 12:00:37 +02:00
commit df1f3c27f7
3 changed files with 24 additions and 9 deletions

View file

@ -1,3 +1,9 @@
# This file is included at http level, so this adds to nginx's MIME table.
# Browsers refuse to run module scripts (the pdf.js worker) served as octet-stream.
types {
text/javascript mjs;
}
server { server {
listen 80; listen 80;
server_name _; server_name _;

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { loadSource, renderPage } from '$lib/pdf/render'; import { MissingSourceError, loadSource, renderPage } from '$lib/pdf/render';
import { vault } from '$lib/storage/vault.svelte'; import { vault } from '$lib/storage/vault.svelte';
import type { Origin } from '$lib/model/types'; import type { Origin } from '$lib/model/types';
@ -13,7 +13,7 @@
let { origin, width, height, scale }: Props = $props(); let { origin, width, height, scale }: Props = $props();
let canvas: HTMLCanvasElement; let canvas: HTMLCanvasElement;
let failed = $state(false); let failure = $state<'missing' | 'error' | null>(null);
// Render at a stepped resolution so zooming doesn't re-render constantly. // Render at a stepped resolution so zooming doesn't re-render constantly.
const STEPS = [0.25, 0.5, 1, 1.5, 2, 3, 4]; const STEPS = [0.25, 0.5, 1, 1.5, 2, 3, 4];
@ -35,9 +35,13 @@
const doc = await loadSource(sourceId, () => vault.getSource(sourceId)); const doc = await loadSource(sourceId, () => vault.getSource(sourceId));
if (cancelled) return; if (cancelled) return;
job = renderPage(doc, pageIndex, canvas, res); job = renderPage(doc, pageIndex, canvas, res);
failed = false; failure = null;
} catch { } catch (e) {
failed = true; if (e instanceof MissingSourceError) failure = 'missing';
else {
failure = 'error';
console.error(`Could not render source PDF “${origin.name}”`, e);
}
} }
}, 120); }, 120);
return () => { return () => {
@ -48,9 +52,11 @@
}); });
</script> </script>
<canvas bind:this={canvas} class="bg" class:failed></canvas> <canvas bind:this={canvas} class="bg"></canvas>
{#if failed} {#if failure === 'missing'}
<div class="missing">Source PDF “{origin.name}” is not available</div> <div class="missing">Source PDF “{origin.name}” is not stored on this device</div>
{:else if failure === 'error'}
<div class="missing">Could not display “{origin.name}” (see the browser console)</div>
{/if} {/if}
<style> <style>

View file

@ -8,12 +8,15 @@ pdfjs.GlobalWorkerOptions.workerSrc = workerUrl;
const docs = new Map<string, Promise<PDFDocumentProxy>>(); const docs = new Map<string, Promise<PDFDocumentProxy>>();
/** The source PDF's bytes aren't stored on this device (as opposed to pdf.js failing on them). */
export class MissingSourceError extends Error {}
export function loadSource(sourceId: string, getBytes: () => Promise<Uint8Array | undefined>) { export function loadSource(sourceId: string, getBytes: () => Promise<Uint8Array | undefined>) {
let p = docs.get(sourceId); let p = docs.get(sourceId);
if (!p) { if (!p) {
p = (async () => { p = (async () => {
const bytes = await getBytes(); const bytes = await getBytes();
if (!bytes) throw new Error(`Missing source PDF ${sourceId}`); if (!bytes) throw new MissingSourceError(`Missing source PDF ${sourceId}`);
// pdf.js transfers the buffer to its worker, so hand it a copy. // pdf.js transfers the buffer to its worker, so hand it a copy.
return pdfjs.getDocument({ data: bytes.slice() }).promise; return pdfjs.getDocument({ data: bytes.slice() }).promise;
})(); })();