From 7b91a1eefcf2eab790accff399bdc841c5b5d530 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Fri, 23 Oct 2026 17:32:02 +0200 Subject: [PATCH] idml: explicit zero cell edge weights hide the default table border (#1623) --- crates/idml/src/import.rs | 9 ++++++++- crates/idml/src/tests.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/crates/idml/src/import.rs b/crates/idml/src/import.rs index ef504065e..dda5ac27e 100644 --- a/crates/idml/src/import.rs +++ b/crates/idml/src/import.rs @@ -2170,9 +2170,12 @@ impl<'r> Importer<'r> { } // Table-local options override the named table style. Cell styles are already // materialized independently, so their edges retain their higher precedence. + let mut border_unset = style.border.is_none() && style.borders.iter().all(|b| b.is_empty()); let mut borders = std::array::from_fn::<_, 4, _>(|i| t.options.border_for(i).clone()); for (side, border) in ["TopBorder", "LeftBorder", "BottomBorder", "RightBorder"].iter().zip(&mut borders) { - self.cell_stroke_attrs(e, side).apply_to(border); + let attrs = self.cell_stroke_attrs(e, side); + border_unset &= attrs.is_empty(); + attrs.apply_to(border); } t.options.border = borders[0].clone(); t.options.borders = borders.map(Some); @@ -2243,6 +2246,10 @@ impl<'r> Importer<'r> { cell.stroke_priorities[i] = priority; // Preserve style-defined edges and #102's positive-priority local overrides. cell.border_overrides[i] |= priority > 0; + // No table or table style border is given anywhere, so the built-in 1 pt default must not + // draw over an outer edge the cell explicitly hides (weight 0 or the None swatch), as InDesign draws nothing. + let hidden = attrs.weight == Some(0.0) || attrs.color.as_deref() == Some(swatch::NONE); + cell.border_overrides[i] |= border_unset && hidden; } if let Some(slot) = t.cell_mut(r, c) { *slot = cell; diff --git a/crates/idml/src/tests.rs b/crates/idml/src/tests.rs index 37fb2af50..b0119274f 100644 --- a/crates/idml/src/tests.rs +++ b/crates/idml/src/tests.rs @@ -1100,6 +1100,35 @@ fn imports_and_round_trips_explicit_cell_border_overrides() { assert_eq!(roundtrip.cell(0, 1).unwrap().border_overrides, [false; 4]); } +#[test] +fn explicitly_hidden_cell_edges_hide_the_default_table_border() { + // No table border or table style is given, and every cell edge is explicitly hidden (issue #1623): + // the first cell by weight 0, the second by the None swatch. + let cell = |name: &str, attr: &str, value: &str| { + format!( + r#" + X"# + ) + }; + let story = format!( + r#" + + + + + {}{} +
"#, + cell("0:0", "StrokeWeight", "0"), + cell("1:0", "StrokeColor", "Swatch/None") + ); + let d = import_idml(&fixture_with_story(&story)).unwrap(); + d.check().unwrap(); + let table = d.stories.values().flat_map(|s| s.tables.values()).next().unwrap(); + for c in 0..2 { + assert_eq!(table.cell(0, c).unwrap().border_overrides, [true; 4], "cell {c} suppresses the table border"); + } +} + #[test] fn round_trips_footnotes_and_options() { let mut d = Document::new(&NewDocument::default());