feat(frontend): replace iframe with PDF.js viewer (#39)

- Install pdfjs-dist v5 and add optimizeDeps pre-bundle config
- New PdfViewer.svelte component: renders each page on a <canvas> with
  correct device-pixel-ratio scaling, overlays a text layer (enables
  text selection; foundation for annotations in #40), prev/next
  navigation, zoom controls, and lazy page rendering (only current ±1
  pre-fetched — avoids freezing on multi-page documents)
- Replace the <iframe> in documents/[id]/+page.svelte with PdfViewer;
  image attachments continue to use <img>; detection now uses
  doc.contentType instead of filename extension
- Unit tests for navigation controls and page counter (pdfjs mocked)
- E2E tests: PDF renders as canvas (not iframe), nav controls visible,
  image fallback stays as <img>; minimal.pdf fixture for upload tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-23 19:10:02 +01:00
parent 4f69457a68
commit 5fb6a1eec0
9 changed files with 756 additions and 9 deletions

View File

@@ -207,6 +207,28 @@
resolved "https://registry.npmjs.org/@lix-js/server-protocol-schema/-/server-protocol-schema-0.1.1.tgz"
integrity sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==
"@napi-rs/canvas-linux-x64-gnu@0.1.97":
version "0.1.97"
resolved "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.97.tgz"
integrity sha512-iDUBe7AilfuBSRbSa8/IGX38Mf+iCSBqoVKLSQ5XaY2JLOaqz1TVyPFEyIck7wT6mRQhQt5sN6ogfjIDfi74tg==
"@napi-rs/canvas@^0.1.95":
version "0.1.97"
resolved "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.97.tgz"
integrity sha512-8cFniXvrIEnVwuNSRCW9wirRZbHvrD3JVujdS2P5n5xiJZNZMOZcfOvJ1pb66c7jXMKHHglJEDVJGbm8XWFcXQ==
optionalDependencies:
"@napi-rs/canvas-android-arm64" "0.1.97"
"@napi-rs/canvas-darwin-arm64" "0.1.97"
"@napi-rs/canvas-darwin-x64" "0.1.97"
"@napi-rs/canvas-linux-arm-gnueabihf" "0.1.97"
"@napi-rs/canvas-linux-arm64-gnu" "0.1.97"
"@napi-rs/canvas-linux-arm64-musl" "0.1.97"
"@napi-rs/canvas-linux-riscv64-gnu" "0.1.97"
"@napi-rs/canvas-linux-x64-gnu" "0.1.97"
"@napi-rs/canvas-linux-x64-musl" "0.1.97"
"@napi-rs/canvas-win32-arm64-msvc" "0.1.97"
"@napi-rs/canvas-win32-x64-msvc" "0.1.97"
"@playwright/test@^1.58.2":
version "1.58.2"
resolved "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz"
@@ -1462,6 +1484,11 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
node-readable-to-web-readable-stream@^0.4.2:
version "0.4.2"
resolved "https://registry.npmjs.org/node-readable-to-web-readable-stream/-/node-readable-to-web-readable-stream-0.4.2.tgz"
integrity sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==
obug@^2.1.0, obug@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz"
@@ -1553,6 +1580,14 @@ pathe@^2.0.3:
resolved "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz"
integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==
pdfjs-dist@^5.5.207:
version "5.5.207"
resolved "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.5.207.tgz"
integrity sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==
optionalDependencies:
"@napi-rs/canvas" "^0.1.95"
node-readable-to-web-readable-stream "^0.4.2"
picocolors@^1.0.0, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz"