From b8201668728aebba8344057a169c11673c5b4e26 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 08:15:00 -0500 Subject: [PATCH] Read paragraph list and span settings through shared model --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 4 ++-- crates/idml/src/export/text_attrs.rs | 3 +++ crates/idml/src/import/text_attrs.rs | 22 ++++++++++++---------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0e4fb15a..9ee481588 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,10 +1242,10 @@ dependencies = [ [[package]] name = "craft-idml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82#6f4960876fd0d66d46f693278f7df10a17859a82" +source = "git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf#61a42fdf95c95e3d20a83e1242fc925585008fbf" dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", "thiserror 2.0.21", ] @@ -1656,7 +1656,7 @@ dependencies = [ [[package]] name = "craft-xml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82#6f4960876fd0d66d46f693278f7df10a17859a82" +source = "git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf#61a42fdf95c95e3d20a83e1242fc925585008fbf" dependencies = [ "quick-xml 0.41.0", "thiserror 2.0.21", @@ -1730,7 +1730,7 @@ dependencies = [ [[package]] name = "craft-zip" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82#6f4960876fd0d66d46f693278f7df10a17859a82" +source = "git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf#61a42fdf95c95e3d20a83e1242fc925585008fbf" dependencies = [ "flate2", "thiserror 2.0.21", @@ -2021,7 +2021,7 @@ dependencies = [ "craft-prepress", "craft-print", "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)", - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=f23b0f33f0d00b157476533a43cbbcfd901aa1f1)", "designcraft-color", "designcraft-compose", @@ -2103,9 +2103,9 @@ name = "designcraft-idml" version = "0.20.1" dependencies = [ "craft-file-formats", - "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", "craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)", - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", "designcraft-color", "designcraft-compose", "designcraft-doc", @@ -2222,7 +2222,7 @@ version = "0.20.1" dependencies = [ "craft-docx", "craft-file-formats", - "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=6f4960876fd0d66d46f693278f7df10a17859a82)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=61a42fdf95c95e3d20a83e1242fc925585008fbf)", "craft-rtf", "craft-wordmodel", "craft-xlsx", diff --git a/Cargo.toml b/Cargo.toml index a9184f993..e4a20001b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,10 @@ craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "4052591363 craft-designcraft-format = { git = "https://github.com/storytold/craft-libs", rev = "19692b6190465671e41967c75d0cd4c439d0c84c", version = "=0.1.0" } craft-eps = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } craft-epub = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } -craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "6f4960876fd0d66d46f693278f7df10a17859a82", version = "=0.1.0" } +craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "61a42fdf95c95e3d20a83e1242fc925585008fbf", version = "=0.1.0" } craft-indd = { git = "https://github.com/storytold/craft-libs", rev = "47bf5650b0d503b97bfb5e841746c4957897d11f", version = "=0.1.0" } craft-svg = { git = "https://github.com/storytold/craft-libs", rev = "cc23ffd4d26f3074808e2187d332564817624f8f", version = "=0.1.0", features = ["tree-render", "tree-text"] } -craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "6f4960876fd0d66d46f693278f7df10a17859a82", version = "=0.1.0" } +craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "61a42fdf95c95e3d20a83e1242fc925585008fbf", version = "=0.1.0" } craft-xml-dtd = { package = "craft-xml", git = "https://github.com/storytold/craft-libs", rev = "f23b0f33f0d00b157476533a43cbbcfd901aa1f1", version = "=0.1.0" } craft-rtf = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } craft-xlsx = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" } diff --git a/crates/idml/src/export/text_attrs.rs b/crates/idml/src/export/text_attrs.rs index b5144a13f..1e27e4544 100644 --- a/crates/idml/src/export/text_attrs.rs +++ b/crates/idml/src/export/text_attrs.rs @@ -417,6 +417,7 @@ impl<'a> Ex<'a> { n!(a, el, span_space_before, "SpanColumnMinSpaceBefore"); n!(a, el, span_space_after, "SpanColumnMinSpaceAfter"); let list = craft_idml::model::ParagraphListValues { + applied_list: None, list_type: a.list_type.map(|list| { match list { ListType::None => "NoList", @@ -439,6 +440,8 @@ impl<'a> Ex<'a> { restart_numbers: a.restart_numbers, restart_after_level: a.restart_after_level, restart_after_specific_level: a.restart_after_level.is_some_and(|level| level != 0), + numbering_continue: None, + numbering_start_at: None, bullet_font: a.bullet_font.clone(), bullet_font_style: a.bullet_font_style.clone(), }; diff --git a/crates/idml/src/import/text_attrs.rs b/crates/idml/src/import/text_attrs.rs index 7264e19fb..f060201ec 100644 --- a/crates/idml/src/import/text_attrs.rs +++ b/crates/idml/src/import/text_attrs.rs @@ -156,6 +156,8 @@ impl<'r> Importer<'r> { let alignment = craft_idml::model::ParagraphAlignmentValues::from_el(&crate::xml::to_craft(e)); let flow = craft_idml::model::ParagraphFlowValues::from_el(&crate::xml::to_craft(e)); let cjk = craft_idml::model::CjkParagraphValues::from_el(&crate::xml::to_craft(e)); + let span = craft_idml::model::ParagraphSpanValues::from_el(&crate::xml::to_craft(e)); + let list = craft_idml::model::ParagraphListValues::from_el(&crate::xml::to_craft(e)); a.align = alignment.justification.as_deref().and_then(|v| names::align_in(v.trim())); a.kinsoku_hang = cjk.kinsoku_hang.as_deref().and_then(|v| match v { "None" => Some(designcraft_doc::cjk::KinsokuHang::None), @@ -194,13 +196,13 @@ impl<'r> Importer<'r> { a.first_line_indent = alignment.first_line_indent; a.last_line_indent = alignment.last_line_indent; a.space_before = alignment.space_before; - if let Some(r) = e.prop("AppliedNumberingList") { + if let Some(r) = list.applied_list.as_deref() { let r = r.trim().trim_start_matches("NumberingList/"); a.list_name = Some(if r.starts_with("$ID/") { String::new() } else { unescape_id(r) }); } - match e.prop("NumberingContinue").as_deref().map(str::trim) { - Some("false") => a.start_at = Some(e.num("NumberingStartAt").map(|n| n.max(1.0) as u32)), - Some("true") => a.start_at = Some(None), + match list.numbering_continue { + Some(false) => a.start_at = Some(list.numbering_start_at.map(|value| value.max(1.0) as u32)), + Some(true) => a.start_at = Some(None), _ => {} } self.read_nested_styles(e, &mut a); @@ -255,16 +257,16 @@ impl<'r> Importer<'r> { a.keep_first = flow.keep_first_lines.map(|v| v.max(0.0) as u32); a.keep_last = flow.keep_last_lines.map(|v| v.max(0.0) as u32); a.start_paragraph = flow.start_paragraph.as_deref().and_then(|v| names::start_para_in(v.trim())); - if let Some(t) = e.prop("SpanColumnType") { - let n = e.prop("SpanSplitColumnCount").and_then(|v| v.trim().parse::().ok()).unwrap_or(0); + if let Some(t) = span.kind { + let n = span.split_column_count.unwrap_or(0); a.span_columns = Some(match t.trim() { "SpanColumns" => SpanColumns::Span(n), "SplitColumns" => SpanColumns::Split(n.max(2)), _ => SpanColumns::Single, }); } - a.split_inside_gutter = e.num("SplitColumnInsideGutter").filter(|v| v.is_finite()); - a.split_outside_gutter = e.num("SplitColumnOutsideGutter").filter(|v| v.is_finite()); + a.split_inside_gutter = span.inside_gutter; + a.split_outside_gutter = span.outside_gutter; a.rule_above = self.rule(e, "RuleAbove"); a.rule_below = self.rule(e, "RuleBelow"); a.tabs = self.read_tabs(e); @@ -322,8 +324,8 @@ impl<'r> Importer<'r> { a.shading_bottom = boxes.shading_bottom.as_deref().map(|value| names::box_bottom_in(value.trim())); a.shading_clip = boxes.shading_clip; a.shading_nonprinting = boxes.shading_nonprinting; - a.span_space_before = e.num("SpanColumnMinSpaceBefore").filter(|v| v.is_finite()); - a.span_space_after = e.num("SpanColumnMinSpaceAfter").filter(|v| v.is_finite()); + a.span_space_before = span.space_before; + a.span_space_after = span.space_after; a.list_level = list.level.map(|value| value.round().clamp(1.0, designcraft_doc::LIST_LEVELS as f64) as u32); if let Some(style) = list.bullet_character_style { a.bullet_char_style = Some(self.char_style_ref(style.trim()));