feat(preview): inline .pptx rendering via PptxViewJS (#297) #319

Merged
Cordy merged 4 commits from feat/pptx-preview into main 2026-08-27 12:33:01 +00:00
Owner

Third and final slice of #297. Renders .pptx inline (canvas, slide-by-slide with prev/next nav) instead of the download card.

Approach

  • Vendored, not CDN. vendor-pptxviewjs.min.js (PptxViewJS 1.1.9, MIT, 621 KB) + vendor-chart.umd.min.js (Chart.js 4.4.1, MIT, 205 KB), flat in web/static/, served from Cairn's own origin behind auth. Reuses the already-vendored JSZip. Lazy-loaded on first .pptx preview.
  • Load order. jszip → chart.js (then Chart.register(...registerables) to replicate chart.js/auto, so chart slides render) → PptxViewJS. PptxViewJS's UMD reads globals JSZip and Chart.
  • Rendering. new PptxViewJS.PPTXViewer({ canvas })loadFile(blob)render(); a small footer bar gives ‹ / › navigation and an i / N counter via prevSlide/nextSlide/getCurrentSlideIndex/getSlideCount. 40 MB guard; pvPath staleness guard after each await; every viewer call is defensively wrapped, so any failure (including a slide the renderer can't handle) falls back to the pvNoPreview card.
  • Scope. Gated strictly on pptx (OOXML). .ppt (legacy binary) still falls through to the card.

Verification

node --check on all page script blocks (passed in the build workflow). pptx fidelity varies by deck and is the operator's visual check on the dogfood after deploy; the defensive wrapping guarantees a graceful card fallback rather than a broken panel on anything PptxViewJS can't render.

Closes the three preview slices of #297 (docx #317, xlsx #318, pptx here). Recommend a follow-up pass on #297 to spot-check real-world fidelity and decide whether .doc/.ppt/.odt legacy formats are worth additional converters.

Third and final slice of #297. Renders `.pptx` inline (canvas, slide-by-slide with prev/next nav) instead of the download card. ## Approach - **Vendored, not CDN.** `vendor-pptxviewjs.min.js` (PptxViewJS 1.1.9, MIT, 621 KB) + `vendor-chart.umd.min.js` (Chart.js 4.4.1, MIT, 205 KB), flat in `web/static/`, served from Cairn's own origin behind auth. Reuses the already-vendored JSZip. Lazy-loaded on first `.pptx` preview. - **Load order.** jszip → chart.js (then `Chart.register(...registerables)` to replicate `chart.js/auto`, so chart slides render) → PptxViewJS. PptxViewJS's UMD reads globals `JSZip` and `Chart`. - **Rendering.** `new PptxViewJS.PPTXViewer({ canvas })` → `loadFile(blob)` → `render()`; a small footer bar gives `‹ / ›` navigation and an `i / N` counter via `prevSlide`/`nextSlide`/`getCurrentSlideIndex`/`getSlideCount`. 40 MB guard; `pvPath` staleness guard after each await; **every** viewer call is defensively wrapped, so any failure (including a slide the renderer can't handle) falls back to the `pvNoPreview` card. - **Scope.** Gated strictly on `pptx` (OOXML). `.ppt` (legacy binary) still falls through to the card. ## Verification `node --check` on all page script blocks (passed in the build workflow). pptx fidelity varies by deck and is the operator's visual check on the dogfood after deploy; the defensive wrapping guarantees a graceful card fallback rather than a broken panel on anything PptxViewJS can't render. Closes the three preview slices of #297 (docx #317, xlsx #318, pptx here). Recommend a follow-up pass on #297 to spot-check real-world fidelity and decide whether `.doc/.ppt/.odt` legacy formats are worth additional converters.
Cordy merged commit 539a66f4dd into main 2026-08-27 12:33:01 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#319
No description provided.