feat(preview): inline .xlsx/.xls/.ods rendering via SheetJS (#297) #318

Merged
Cordy merged 4 commits from feat/xlsx-preview into main 2026-08-27 12:18:03 +00:00
Owner

Second slice of #297. Renders spreadsheets inline as HTML tables instead of the download card.

Approach

  • Vendored, not CDN. vendor-xlsx.full.min.js (SheetJS CE, Apache-2.0, ~930 KB) sits flat in web/static/, bundled into the embedded webdist and served from Cairn's own origin (behind auth). Lazy-loaded on first spreadsheet preview via the same _loadScript helper added for docx.
  • Rendering. XLSX.read(bytes)XLSX.utils.sheet_to_html into a scrollable, scoped-styled container. Multi-sheet workbooks get a <select> sheet picker; single-sheet ones render directly. 25 MB guard; pvPath staleness guard after each await; failure falls back to the pvNoPreview card.
  • Scope. Gated on xlsx / xls / ods (all read by SheetJS). csv/tsv keep their existing text-preview behaviour (unchanged). pptx is the last slice.

Verification

node --check on all page script blocks (passed in the build workflow). Real spreadsheet rendering is the operator's visual check on the dogfood after deploy.

Second slice of #297. Renders spreadsheets inline as HTML tables instead of the download card. ## Approach - **Vendored, not CDN.** `vendor-xlsx.full.min.js` (SheetJS CE, Apache-2.0, ~930 KB) sits flat in `web/static/`, bundled into the embedded `webdist` and served from Cairn's own origin (behind auth). Lazy-loaded on first spreadsheet preview via the same `_loadScript` helper added for docx. - **Rendering.** `XLSX.read(bytes)` → `XLSX.utils.sheet_to_html` into a scrollable, scoped-styled container. Multi-sheet workbooks get a `<select>` sheet picker; single-sheet ones render directly. 25 MB guard; `pvPath` staleness guard after each await; failure falls back to the `pvNoPreview` card. - **Scope.** Gated on `xlsx` / `xls` / `ods` (all read by SheetJS). `csv`/`tsv` keep their existing text-preview behaviour (unchanged). pptx is the last slice. ## Verification `node --check` on all page script blocks (passed in the build workflow). Real spreadsheet rendering is the operator's visual check on the dogfood after deploy.
Cordy merged commit eda4695e06 into main 2026-08-27 12:18:03 +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#318
No description provided.