diff --git a/apps/deckcraft-cli/src/help.rs b/apps/deckcraft-cli/src/help.rs index 5803dc81..d6158f46 100644 --- a/apps/deckcraft-cli/src/help.rs +++ b/apps/deckcraft-cli/src/help.rs @@ -50,19 +50,22 @@ OUT-t0.250.png and so on. Prints each image's path, size, transition and time. usage: "convert IN OUT", summary: "save a presentation in the format OUT's extension names", details: "Opens IN (.deckcraft or .pptx) and writes it to OUT, in the format OUT's extension names: -.deckcraft, .pptx, .pdf, .txt or .md for the outline, .png or .jpg for the first slide. Any other -extension is written as .deckcraft. Prints OUT. +.deckcraft, .pptx, .pdf, .txt or .md for the outline, .png or .jpg for the first slide, .gif for an +animated GIF with one frame per slide. Other extensions are refused. Prints OUT. deckcraft-cli convert deck.deckcraft deck.pptx", }, Subcommand { name: "run", - usage: "run [--in FILE | --sample] [--cmd COMMAND[=PARAMS]]... [--save OUT] [--export OUT] [--print]", + usage: "run [--in FILE | --sample] [--cmd COMMAND[=PARAMS]]... [--save OUT] [--export OUT [--export-params JSON]] [--print]", summary: "run commands on a presentation, then save or export it", details: "Runs commands, in order, on one presentation: FILE with --in, the sample presentation with --sample, else a new one with an empty title slide. Then --save writes the presentation: .deckcraft keeps everything; .pptx, .pdf and .md (the outline) are written as convert writes them. --export writes the -current slide as .png or .jpg, or the presentation as .pdf or .pptx. +current slide as .png or .jpg, or the presentation as .pdf, .pptx or an animated .gif (one frame per +slide). --export-params passes file.export options as one JSON object, such as +'{\"width\": \"large\", \"secondsPerSlide\": 3, \"loop\": false, \"slides\": [0, 1, 2]}' for a GIF +(`deckcraft-cli describe file.export` lists them). Each --cmd is one command: COMMAND is a command id, then `=`, then the command's parameters as one JSON object. Quote it for the shell. A command that needs no parameters is just its id. diff --git a/apps/deckcraft-cli/tests/convert.rs b/apps/deckcraft-cli/tests/convert.rs index 5de25e51..4f162994 100644 --- a/apps/deckcraft-cli/tests/convert.rs +++ b/apps/deckcraft-cli/tests/convert.rs @@ -21,7 +21,7 @@ fn convert_rejects_output_formats_it_cannot_write() { let out = Command::new(env!("CARGO_BIN_EXE_deckcraft-cli")).args(["run", "--sample", "--export"]).arg(&input).output().unwrap(); assert!(out.status.success(), "{}", String::from_utf8_lossy(&out.stderr)); - for name in ["out.odp", "out.gif", "out.svg", "out.outline", "out"] { + for name in ["out.odp", "out.bmp", "out.svg", "out.outline", "out"] { let target = dir.join(name); let out = cli(&[Path::new("convert"), &input, &target]); assert!(!out.status.success(), "{name}: convert should fail"); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index e0d71985..a81450a0 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -237,7 +237,8 @@ fn writable_format_for_path_rejects_formats_deckcraft_does_not_write() { assert_eq!(f("a.pdf"), Some("pdf")); assert_eq!(f("a.jpg"), Some("jpeg")); assert_eq!(f("a.txt"), Some("outline")); - for path in ["a.odp", "a.gif", "a.svg", "a.outline", "a", "dir.v2/a"] { + assert_eq!(f("a.gif"), Some("gif")); + for path in ["a.odp", "a.bmp", "a.svg", "a.outline", "a", "dir.v2/a"] { assert_eq!(f(path), None, "{path}"); } } diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index a9876e0a..34545650 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -506,6 +506,7 @@ impl SlideApp { "pptx" => ("pptx", "pptx", false), "outline" | "txt" => ("txt", "outline", false), "deckcraft" => ("deckcraft", "deckcraft", false), + "gif" => ("gif", "gif", false), other => { self.set_status(format!("DeckCraft can't export “{other}”")); return false; @@ -535,6 +536,7 @@ impl SlideApp { Ok(if format == "png" { img.to_png_at(dpi) } else { img.to_jpeg_at(92, Some(dpi)) }) } "pdf" => deckcraft_engine::cmd::file::pdf_bytes(&doc, &extra), + "gif" => deckcraft_engine::cmd::file::gif_bytes(&doc, &extra), other => deckcraft_engine::cmd::file::save_bytes(&doc, other), }; self.download(&suggested, bytes)