From 74f9b6fcba6ffaba480b76c55f8456669324a01c Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 08:36:51 -0500 Subject: [PATCH] Parse IDML table of contents styles in shared model --- crates/idml/src/model/document.rs | 51 +++++++++++++++++++++++++++++++ crates/idml/src/model/mod.rs | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/crates/idml/src/model/document.rs b/crates/idml/src/model/document.rs index 14f42f716..746feb8c9 100644 --- a/crates/idml/src/model/document.rs +++ b/crates/idml/src/model/document.rs @@ -4,6 +4,57 @@ use craft_xml::El; use super::{Spread, Story, Values}; +/// One IDML table-of-contents style entry before document style names are resolved. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct TocStyleEntryValues { + pub style: Option, + pub level: Option, + pub page_number_position: Option, + pub separator: Option, + pub entry_style: Option, + pub page_number_style: Option, + pub separator_style: Option, + pub sort: Option, +} + +/// An IDML table-of-contents style and its entry grammar. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct TocStyleValues { + pub self_id: Option, + pub title: Option, + pub title_style: Option, + pub create_bookmarks: Option, + pub entries: Vec, +} + +impl TocStyleValues { + /// Reads a `TOCStyle` element and its bounded `TOCStyleEntry` children. + pub fn from_el(el: &El) -> Self { + let values = Values::of(el); + let mut result = Self { + self_id: values.self_id().map(str::to_owned), + title: values.get("Title").map(str::to_owned), + title_style: values.get("TitleStyle").map(str::to_owned), + create_bookmarks: values.get("CreateBookmarks").or_else(|| values.get("CreatePdfBookmarks")).map(|value| value == "true"), + entries: Vec::new(), + }; + result.entries.extend(el.elements().filter(|entry| entry.local() == "TOCStyleEntry").take(64).map(|entry| { + let values = Values::of(entry); + TocStyleEntryValues { + style: values.get("Name").map(str::to_owned), + level: values.get("Level").and_then(|value| value.trim().parse().ok()), + page_number_position: values.get("PageNumberPosition").map(str::to_owned), + separator: values.get("Separator").map(str::to_owned), + entry_style: values.prop("FormatStyle"), + page_number_style: values.prop("PageNumberStyle"), + separator_style: values.prop("SeparatorStyle"), + sort: values.get("Sort").map(|value| value.trim() == "true"), + } + })); + result + } +} + /// The top-level IDML elements consumed by document importers. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum TopLevelKind { diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index b7e0c45ac..db0edd0cc 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -21,7 +21,7 @@ mod spread; mod story; use craft_xml::{El, Local, Node}; -pub use document::{ModelDocument, TopLevelKind, TopLevelNode}; +pub use document::{ModelDocument, TocStyleEntryValues, TocStyleValues, TopLevelKind, TopLevelNode}; pub use effects::{DirectionalFeatherValues, DropShadowValues, FeatherValues, GradientFeatherValues, OpacityStopValues, TransparencySetting}; pub use geometry::{MAX_PATH_POINTS, PathGeometry, PathGeometryError, PathPoint, SubPath}; pub use preferences::{DocumentPreferences, FootnotePreferences, GridPreferences, TextFramePreferences};