From d412f12f5915daeefd18233d228785cbad37731c Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 05:46:39 -0500 Subject: [PATCH] Expose IDML cell option values --- crates/idml/src/model/mod.rs | 2 +- crates/idml/src/model/story.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 5479d35a5..245990f73 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -26,7 +26,7 @@ pub use spread::{ Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, TextPath, spreads, }; -pub use story::{Ace, CONTAINERS, Cell, Container, ContentPart, Range, Story, StoryPreference, Table, TableChild, TextNode, stories}; +pub use story::{Ace, CONTAINERS, Cell, CellOptions, Container, ContentPart, Range, Story, StoryPreference, Table, TableChild, TextNode, stories}; use craft_xml::{El, Local, Node}; diff --git a/crates/idml/src/model/story.rs b/crates/idml/src/model/story.rs index 1a43b2e48..c8fa0d446 100644 --- a/crates/idml/src/model/story.rs +++ b/crates/idml/src/model/story.rs @@ -150,6 +150,19 @@ pub struct Cell { pub children: Vec, } +/// Format-level options on an IDML table cell, before DesignCraft maps them into its model. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct CellOptions { + pub fill_color: Option, + pub fill_tint: Option, + pub insets: [Option; 4], + pub vertical_justification: Option, + pub first_baseline_offset: Option, + pub minimum_first_baseline_offset: Option, + pub rotation_angle: Option, + pub edge_stroke_priorities: [i32; 4], +} + /// The children of `el` other than ``, as text nodes. fn nodes(el: &El) -> Vec { el.elements().filter(|e| !e.is(Local("Properties"))).map(TextNode::from_el).collect() @@ -443,6 +456,26 @@ impl Cell { (n("ColumnSpan"), n("RowSpan")) } + pub fn options(&self) -> CellOptions { + let inset = |current: &str, legacy: &str| self.values.num(current).or_else(|| self.values.num(legacy)); + let priority = |side: &str| self.values.prop(&format!("{side}StrokePriority")).and_then(|v| v.trim().parse().ok()).unwrap_or(0); + CellOptions { + fill_color: self.values.value("FillColor"), + fill_tint: self.values.num("FillTint"), + insets: [ + inset("TextTopInset", "TopInset"), + inset("TextLeftInset", "LeftInset"), + inset("TextBottomInset", "BottomInset"), + inset("TextRightInset", "RightInset"), + ], + vertical_justification: self.values.value("VerticalJustification"), + first_baseline_offset: self.values.value("FirstBaselineOffset"), + minimum_first_baseline_offset: self.values.num("MinimumFirstBaselineOffset"), + rotation_angle: self.values.num("RotationAngle"), + edge_stroke_priorities: [priority("TopEdge"), priority("LeftEdge"), priority("BottomEdge"), priority("RightEdge")], + } + } + pub fn paragraphs(&self) -> Vec<&Range> { paragraphs(&self.children) }