Skip to content

Export the current slide as an image, or all main slides as one ZIP - #306

Open
lazyeo wants to merge 7 commits into
nyblnet:mainfrom
lazyeo:feature/slides-image-export
Open

Export the current slide as an image, or all main slides as one ZIP#306
lazyeo wants to merge 7 commits into
nyblnet:mainfrom
lazyeo:feature/slides-image-export

Conversation

@lazyeo

@lazyeo lazyeo commented Aug 15, 2026

Copy link
Copy Markdown

Closes #261. This also implements the workflow requested in discussion #243.

What & why

Save ▾ now includes Export slides as images…:

  • export the current slide as PNG or JPEG at 1× or 2×, including a current hidden or state slide;
  • export all main slides as one STORE ZIP with ordered names (slide-01.png, slide-02.png, …);
  • keep PNG transparency and use a white matte for JPEG;
  • skip hidden and state slides in all-main export, matching presentation order.

The implementation uses a document snapshot and the shared renderer. Export is read-only except that an active text edit is committed after the user confirms the dialog. It does not regenerate docId, change #bento-doc, invoke save/update code, or overwrite the deck. It adds no feature dependencies.

The export remains self-contained and offline. Resource preflight accepts only bounded, supported embedded static images and fonts, refuses linked or unsupported resources before mounting a render, and re-checks the selected slide immediately before rasterization. Application CSS is restricted to explicitly app-owned stylesheets, while author CSS animation, transitions, and SMIL motion are frozen at their base frame for deterministic output. Dimension, payload, decoded-pixel, and archive budgets fail closed.

Password-protected decks show an explicit warning that exported images and ZIP files are plaintext; the original encrypted .bento.html, document identity, and model remain unchanged.

Tests are split by responsibility:

  • pure contracts cover selection, naming, sizing, resource policy, image headers, budgets, ZIP bytes, and an independent ZIP reader;
  • the browser rig covers representative pixels and security boundaries, zero export requests with a positive-control request, cancellation/atomicity, and real file:// rasterization;
  • shipped-file acceptance drives the built desktop/mobile UI and verifies current-slide PNG, ordered all-main ZIP output, and the encrypted-deck warning.

The compressed shipped file is 716,123 bytes versus 694,151 bytes for current upstream main, an increase of 21,972 bytes (3.2%) with the same feature dependencies.

Current browser measurements use Chrome. Safari/Firefox, the native OS save panel, and tray/WebExtension writeback are outside this PR's automated coverage.

How I verified it

  • npm run build:single from slides/
  • node scripts/shell-gate.mjs slides/dist-single/Bento_Slides.bento.html
  • scripts/test-slide-image-export.ts: 204/204
  • scripts/test-slide-image-export-browser.ts: 66/66 in Chrome 152 via file://
  • scripts/test-slide-image-export-acceptance.ts: 23/23 against the shipped file
  • scripts/test-sanitize.ts: 140/140 in Chrome
  • node scripts/test-preview.ts: 28/28
  • node scripts/test-export-secrets.ts: 57/57
  • node scripts/test-offline.ts: 33/33
  • node scripts/test-sync.ts: 45,368 checks
  • slides and kernel typechecks
  • i18n packed-table and coverage checks: 793 strings × 8 core locales

Checklist

  • Read the relevant parts of CLAUDE.md and the platform/collaboration docs
  • npm run build:single succeeds from slides/
  • The feature diff does not touch sync; the convergence rig still passes after the upstream merge
  • New UI strings are present in every core catalog and packed.ts is current
  • No document-format change; export preserves the existing document identity and does not serialize or overwrite the deck
  • Did not bump the version, sign, publish, or cut a release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Export slides as images (PNG/JPG) — current slide, or all slides as one ZIP

1 participant