From 4acd6cf90d1e2bf9848bebe8b062e2672db74689 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Fri, 13 Nov 2026 08:43:23 -0800 Subject: [PATCH] Batch: a step with null params gets the artboards a step without params gets A `command.batch` step with `"params": null` now reads as a step without params. Before, it got neither the Artboard tool's selected artboards nor the batch's `artboard`, so a Fit to Artwork Bounds step fitted the first artboard and its journal entry recorded `null`. --- crates/engine/src/cmd/fileio/batch.rs | 3 ++- crates/engine/src/tests/journal.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/fileio/batch.rs b/crates/engine/src/cmd/fileio/batch.rs index 42512f18df..7b41894772 100644 --- a/crates/engine/src/cmd/fileio/batch.rs +++ b/crates/engine/src/cmd/fileio/batch.rs @@ -105,7 +105,8 @@ fn run_steps( if s.active().is_some() { s.begin_interaction(label)?; } - let mut params = c.get("params").cloned().unwrap_or(json!({})); + // `"params": null` reads as no params, so the artboards below can still be added. + let mut params = c.get("params").filter(|v| !v.is_null()).cloned().unwrap_or(json!({})); let key = if crate::ON_ACTIVE_ARTBOARD.contains(&id.as_str()) { Some("artboard") } else { diff --git a/crates/engine/src/tests/journal.rs b/crates/engine/src/tests/journal.rs index 2e31c24721..5b7c3b2322 100644 --- a/crates/engine/src/tests/journal.rs +++ b/crates/engine/src/tests/journal.rs @@ -299,6 +299,27 @@ fn a_batch_fit_step_records_the_batchs_artboard() { assert_eq!(s.journal_for_action(start), [("command.batch".to_string(), json!({"commands": steps}))]); } +/// A batch step with `"params": null` gets the Artboard tool's selected artboards, or else the +/// batch's `artboard`, as a step without params does. +#[test] +fn a_batch_fit_step_with_null_params_gets_the_artboards() { + let fitted = three_fitted_artboards(); + let boards = |s: &Session| s.doc().unwrap().doc.artboards.iter().map(|a| a.rect).collect::>(); + let steps = json!([{"command": "artboard.fitToArt", "params": null}]); + let mut s = Session::new(); + let was = three_artboards_with_art(&mut s); + s.select_tool("artboard", crate::tooling::ViewInfo::default()).unwrap(); + s.set_tool_option("selected", &json!([2, 0])); + s.execute("command.batch", &json!({"artboard": 1, "commands": steps})).unwrap(); + assert_eq!(boards(&s), [fitted[0], was[1], fitted[2]], "the selected artboards"); + let (_, p) = s.journal.last().unwrap().clone(); + assert_eq!(p["commands"][0]["params"], json!({"indices": [0, 2]})); + let mut s = Session::new(); + three_artboards_with_art(&mut s); + s.execute("command.batch", &json!({"artboard": 1, "commands": steps})).unwrap(); + assert_eq!(boards(&s), [was[0], fitted[1], was[2]], "the batch's artboard"); +} + #[test] fn a_save_records_its_date_and_replays_it() { let path = vectorcraft_testkit::temp_dir("journal-save").join("a.vectorcraft").to_string_lossy().into_owned();