diff --git a/crates/engine/src/cmd/fileio/save.rs b/crates/engine/src/cmd/fileio/save.rs index bc0171e19..2cc836ee5 100644 --- a/crates/engine/src/cmd/fileio/save.rs +++ b/crates/engine/src/cmd/fileio/save.rs @@ -520,6 +520,15 @@ fn blank_pages(doc: &Document) -> Document { /// Why a `.ai` file saved without PDF content looks empty elsewhere. const NOT_PDF_COMPATIBLE: &str = "saved without PDF content: VectorCraft opens it as before, other apps show empty pages"; +/// `e`, an error of the export encoders, under the save command `cmd` instead of +/// `document.export`. +fn named_for_save(cmd: &str, e: crate::EngineError) -> crate::EngineError { + match e { + crate::EngineError::BadParams { cmd: c, msg } if c == "document.export" => bad(cmd, msg), + e => e, + } +} + /// The shared Save and Export encoder for PDF-compatible `.ai` files (and `.ait` templates, the /// same file). pub(super) fn encode_ai(cmd: &str, f: &Format, doc: &Document, p: &Value) -> Result { @@ -603,7 +612,7 @@ fn job_for_stamped(s: &Session, st: &DocState, plan: SavePlan, stamped: Option Result { let (cmd, f) = (self.plan.mode.command(), self.plan.format); - let enc = if matches!(f.id, "ai" | "ait") { encode_ai(cmd, f, doc, &self.params)? } else { encode_all(doc, f.id, &self.params)? }; + let enc = if matches!(f.id, "ai" | "ait") { encode_ai(cmd, f, doc, &self.params) } else { encode_all(doc, f.id, &self.params) } + .map_err(|e| named_for_save(cmd, e))?; // A legacy .ai file per artboard. let per_artboard = f.id == "ai" && super::legacy_ai::wanted(cmd, f, &self.params)?; if enc.files.len() != 1 && !per_artboard { diff --git a/crates/engine/src/tests_saveoptions.rs b/crates/engine/src/tests_saveoptions.rs index 9c5bb66a9..ff14cf698 100644 --- a/crates/engine/src/tests_saveoptions.rs +++ b/crates/engine/src/tests_saveoptions.rs @@ -160,6 +160,31 @@ fn pdf_compatible_files_carry_a_pdf() { assert!(vectorcraft_format::pdf_content(&bytes_of(&s.execute("file.saveCopy", &json!({})).unwrap()["dataBase64"])).is_none()); } +#[test] +fn save_option_errors_name_the_save_command() { + let mut s = three_boards(); + for (cmd, p) in [ + ("file.saveCopy", json!({"format": "pdf", "range": "5"})), + ("file.saveCopy", json!({"format": "svg", "artboard": 5})), + ("file.saveAs", json!({"format": "svg", "range": "4"})), + ("document.save", json!({"format": "pdf", "artboards": [3]})), + ("file.saveCopy", json!({"format": "ai", "compress": "yes"})), + ("file.saveCopy", json!({"format": "ai", "pdfCompatible": false, "artboard": "B"})), + ("file.saveCopy", json!({"format": "ai", "aiVersion": 7, "artboard": "B"})), + ("file.saveCopy", json!({"format": "ait", "compress": "yes"})), + ] { + let e = s.execute(cmd, &p).unwrap_err().to_string(); + assert!(e.contains(&format!("`{cmd}`")) && !e.contains("document.export"), "{p}: {e}"); + } + // A native file written to a path. + let dir = Folder::new("save-errors"); + for (cmd, name) in [("document.save", "a.vectorcraft"), ("file.saveAs", "b.vectorcraft"), ("file.saveCopy", "c.vectorcraft")] { + let p = json!({"path": dir.file(name), "compress": "yes"}); + let e = s.execute(cmd, &p).unwrap_err().to_string(); + assert!(e.contains(&format!("`{cmd}`")) && !e.contains("document.export"), "{p}: {e}"); + } +} + #[test] fn ai_without_pdf_content_and_compression() { let mut s = three_boards();