The Print page always laid notes pages and handouts out on portrait US
Letter. It now offers Letter, A4, Legal and A3 in portrait or landscape,
as PowerPoint's Print settings do, and the preview shows the chosen
page. file.export, app.print and the MCP export tool take the same
`paper` and `orientation` params; unknown values are an error. A notes
page keeps its slide within the top half of the page, so landscape
paper still leaves room for the notes. Full-page slides still print on
slide-shaped pages.
Co-authored-by: Cursor <cursoragent@cursor.com>
There was no way to turn a presentation into an animated GIF. file.export now writes one: format
`gif` (or a .gif path), one frame per slide drawn by the slide renderer and shown for
secondsPerSlide, encoded with the `image` crate's GIF encoder (already a dependency, no new
crates) with a 256-colour palette per frame: exact when a slide has 256 colours or fewer,
NeuQuant otherwise. Slides are composited onto white.
Options: width (small 640, medium 960 (default), large 1280, extraLarge 1920, or 16-3840 px; the
height follows the slide's aspect ratio, no side over 3840), secondsPerSlide (0.1-600, default 5,
written in GIF hundredths), loop (forever by default, or once: no NETSCAPE2.0 block), slides (a
list of indices, in play order) and includeHidden (hidden slides are skipped by default).
Out-of-range or wrongly typed values, NaN and infinities are BadParams errors, never panics; at
most 500 frames and 200 million pixels in total, checked before anything is rendered.
- Engine: crates/engine/src/gif_export.rs (options, frame list, size, encoder);
cmd::file::gif_bytes, save_bytes("gif"), format_for_path(".gif").
- UI: the Export… dialog (Command palette; the app has no File menu yet) gets "Animated GIF (.gif)" with Size, Seconds per slide, From/To slide,
Loop forever and Include hidden slides; an invalid range or value keeps the dialog open with a
message. The web build downloads the bytes (image/gif).
- CLI: convert IN OUT.gif, run --export OUT.gif --export-params JSON; usage lists the format and
options.
- MCP: the export tool lists gif and width/secondsPerSlide/loop (slides and includeHidden now
apply to PDF and GIF).
- Docs: file-format parity GIF row, gaps (video export remains), parity checklist row M -> P
(P2 breadth 36% -> 37%, overall 79%), control protocol, MCP, README, ROADMAP progress log.
Transitions and build animations are not animated in the GIF (tracked with video export).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A shape id that was present but not a valid id (negative, not an integer,
larger than u32) was treated as absent, so commands such as text.set and
text.edit silently edited the selected shape instead. id_param now tells three
cases apart: absent (the selection fallback is unchanged), valid, and invalid
(an error naming the command). arrange, edit (select), inspect, review, table,
text and the animation painter pick this up.
slide.go clamped an out-of-range index to the last slide and reported
success, so a request for slide 99 of a short deck landed on the last slide
without a word. It now returns an error and stays on the current slide. A slide
id beyond u32 is reported as an unknown slide instead of being read as id 0.
file.export with an explicit format outside png, jpeg, jpg, pdf, pptx, potx,
ppsx, deckcraft, outline and txt fell through to the native deckcraft zip, so a
request for "docx" reported success and wrote a deckcraft archive under that
name. It now returns an error and writes nothing. A format inferred from the
file extension behaves as before.
tools/list described export as png/jpeg/pptx/outline only, with no PDF parameters, although
file.export (which the tool runs) writes PDF slides, notes pages and handouts. The tool's
description now names PDF, format is an enum of the formats file.export writes, and the schema
lists the PDF options: layout, perPage, dpi, slides, includeHidden, textLayer and frame.
Co-authored-by: lloyd <lloyd@stackworx.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>