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());