From 1239163a1aebc95fda0e34de41b83c9fd4185fbc Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 07:21:07 -0500 Subject: [PATCH] Model IDML paragraph list properties --- crates/idml/src/model/mod.rs | 5 +-- crates/idml/src/model/resources.rs | 51 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/crates/idml/src/model/mod.rs b/crates/idml/src/model/mod.rs index 85d284d99..56fa5ff12 100644 --- a/crates/idml/src/model/mod.rs +++ b/crates/idml/src/model/mod.rs @@ -29,8 +29,9 @@ pub use resources::{ CjkCharacterValues, ColorDefinition, ColorGroup, ColorGroupDefinition, ColorGroupMember, ColorSpace, CompositeFontDefinition, CompositeFontEntryDefinition, EpubExportTagMap, FontDefinition, FontFamilyDefinition, FontsPart, GradientDefinition, GradientStop, GradientStopDefinition, GradientStopValue, GraphicPart, GrepStyleValue, Ink, InkDefinition, MojikumiRow, NestedLineStyleValue, NestedStyleValue, - NestedStyleValues, OpenTypeFeatureValues, StrokeDefinition, StrokeStyle, StrokeStyleKind, Style, StyleGroup, StyleGroupWriter, StyleKind, - StyleNode, Swatch, SwatchKind, TabStopValues, TintDefinition, color_groups, inks, named, preference, stroke_styles, style_groups, swatches, + NestedStyleValues, OpenTypeFeatureValues, ParagraphListValues, StrokeDefinition, StrokeStyle, StrokeStyleKind, Style, StyleGroup, + StyleGroupWriter, StyleKind, StyleNode, Swatch, SwatchKind, TabStopValues, TintDefinition, color_groups, inks, named, preference, stroke_styles, + style_groups, swatches, }; pub use spread::{ Graphic, GraphicChild, GraphicKind, Guide, ItemChild, ItemKind, Link, MarginPreference, Page, PageChild, PageItem, Spread, SpreadChild, TextPath, diff --git a/crates/idml/src/model/resources.rs b/crates/idml/src/model/resources.rs index 0bc98ca9f..da2baea99 100644 --- a/crates/idml/src/model/resources.rs +++ b/crates/idml/src/model/resources.rs @@ -11,6 +11,57 @@ fn others(el: &El) -> impl Iterator { el.elements().filter(|e| !e.is(Local("Properties"))) } +/// Raw bullet and numbering properties on an IDML paragraph style or range. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct ParagraphListValues { + pub list_type: Option, + pub numbering_format: Option, + pub expression: Option, + pub separator: Option, + pub bullet_type: Option, + pub bullet_value: Option, + pub balance_ragged: Option, + pub level: Option, + pub bullet_character_style: Option, + pub numbering_character_style: Option, + pub bullet_alignment: Option, + pub numbering_alignment: Option, + pub restart_numbers: Option, + pub restart_after_level: Option, + pub restart_after_specific_level: bool, + pub bullet_font: Option, + pub bullet_font_style: Option, +} + +impl ParagraphListValues { + pub fn from_el(el: &El) -> Self { + let values = Values::of(el); + let restart = values.prop_el("NumberingRestartPolicies"); + let restart_after_level = restart.map(|policy| policy.attr("LowerLevel").and_then(|value| value.trim().parse::().ok()).unwrap_or(0)); + let restart_after_specific_level = restart.is_some_and(|policy| policy.attr("RestartPolicy").map(str::trim) == Some("SpecificPreviousLevel")); + let bullet = values.prop_el("BulletChar"); + Self { + list_type: values.prop("BulletsAndNumberingListType"), + numbering_format: values.prop("NumberingFormat"), + expression: values.prop("NumberingExpression"), + separator: values.prop("BulletsTextAfter"), + bullet_type: bullet.and_then(|value| value.attr("BulletCharacterType")).map(str::to_owned), + bullet_value: bullet.and_then(|value| value.attr("BulletCharacterValue")).map(str::to_owned), + balance_ragged: values.prop("BalanceRaggedLines"), + level: values.num("NumberingLevel"), + bullet_character_style: values.prop("BulletsCharacterStyle"), + numbering_character_style: values.prop("NumberingCharacterStyle"), + bullet_alignment: values.prop("BulletsAlignment"), + numbering_alignment: values.prop("NumberingAlignment"), + restart_numbers: values.boolean("NumberingApplyRestartPolicy"), + restart_after_level, + restart_after_specific_level, + bullet_font: values.prop("BulletsFont"), + bullet_font_style: values.prop("BulletsFontStyle"), + } + } +} + /// One IDML nested paragraph style entry, before the caller resolves its character style. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct NestedStyleValue {