From 4a7fc340f8af2c09ab5cb67e5f9a1e5869e9ec9e Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 8 Nov 2026 15:10:20 +0100 Subject: [PATCH] Clamp negative gutter in file.new and file.savePreset to 0 Found while testing crates/engine/src/cmd/file/new.rs:179 (apply_settings: `nd.gutter = f64_or(p, "gutter", nd.gutter)`); compare crates/engine/src/cmd/layout/margins.rs:101 (`g.max(0.0)`) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/file/new.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/file/new.rs b/crates/engine/src/cmd/file/new.rs index e02ce11e4..c59783442 100644 --- a/crates/engine/src/cmd/file/new.rs +++ b/crates/engine/src/cmd/file/new.rs @@ -176,7 +176,7 @@ fn apply_settings(nd: &mut NewDocument, p: &Value) { nd.start_page = p.get("startPage").and_then(Value::as_u64).map(|v| v.clamp(1, 99_999) as u32).unwrap_or(nd.start_page); nd.facing_pages = p.get("facingPages").and_then(Value::as_bool).unwrap_or(nd.facing_pages); nd.columns = p.get("columns").and_then(Value::as_u64).map(|v| v.clamp(1, 216) as u32).unwrap_or(nd.columns); - nd.gutter = f64_or(p, "gutter", nd.gutter); + nd.gutter = p.get("gutter").and_then(Value::as_f64).filter(|g| g.is_finite()).map_or(nd.gutter, |g| g.max(0.0)); nd.primary_text_frame = p.get("primaryTextFrame").and_then(Value::as_bool).unwrap_or(nd.primary_text_frame); match p.get("margins") { Some(Value::Number(n)) => nd.margins = designcraft_doc::Margins::uniform(n.as_f64().unwrap_or(36.0)), @@ -254,6 +254,16 @@ mod new_document_tests { assert!(s.execute("file.new", &json!({"preset": "Newsletter"})).is_err()); } + #[test] + fn negative_gutter_is_clamped_to_zero() { + let mut s = Session::new(); + s.execute("file.new", &json!({"gutter": -50, "columns": 2})).unwrap(); + let d = &s.doc().unwrap().doc; + assert_eq!(d.page(0).unwrap().columns.gutter, 0.0); + s.execute("file.savePreset", &json!({"name": "Tight", "gutter": -50, "columns": 2})).unwrap(); + assert_eq!(s.prefs.document_presets[0].gutter, 0.0); + } + #[test] fn new_document_takes_intent_units_start_page_bleed_and_slug() { let mut s = Session::new();