Read IDML table of contents styles through shared model

This commit is contained in:
Dylan M. Taylor committed 2026-11-13 08:37:27 -05:00
1 parent d939af608a
commit eeb085fb63
3 files changed
+48 -49

No files matched your search

Generated
+26 -26
View File
@@ -1242,10 +1242,10 @@ dependencies = [
[[package]]
name = "craft-idml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8#08531a7b46b4e09f43c77f52e13d9f918e7ba9f8"
source = "git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527#ecf0f57a20bf229d85f8c19e2a1c198c8de30527"
dependencies = [
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"thiserror 2.0.21",
]
@@ -1644,15 +1644,6 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8#08531a7b46b4e09f43c77f52e13d9f918e7ba9f8"
dependencies = [
"quick-xml 0.41.0",
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
@@ -1689,6 +1680,15 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527#ecf0f57a20bf229d85f8c19e2a1c198c8de30527"
dependencies = [
"quick-xml 0.41.0",
"thiserror 2.0.21",
]
[[package]]
name = "craft-xml"
version = "0.1.0"
@@ -1717,16 +1717,6 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8#08531a7b46b4e09f43c77f52e13d9f918e7ba9f8"
dependencies = [
"flate2",
"thiserror 2.0.21",
"zip 9.1.1",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
@@ -1757,6 +1747,16 @@ dependencies = [
"zip 9.1.1",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
source = "git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527#ecf0f57a20bf229d85f8c19e2a1c198c8de30527"
dependencies = [
"flate2",
"thiserror 2.0.21",
"zip 9.1.1",
]
[[package]]
name = "craft-zip"
version = "0.1.0"
@@ -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=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"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=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"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=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"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=08531a7b46b4e09f43c77f52e13d9f918e7ba9f8)",
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ecf0f57a20bf229d85f8c19e2a1c198c8de30527)",
"craft-rtf",
"craft-wordmodel",
"craft-xlsx",
+2 -2
View File
@@ -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 = "93d0998383aa150fa50a2ffbf49ef37786e37eca", 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 = "08531a7b46b4e09f43c77f52e13d9f918e7ba9f8", version = "=0.1.0" }
craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "ecf0f57a20bf229d85f8c19e2a1c198c8de30527", 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 = "08531a7b46b4e09f43c77f52e13d9f918e7ba9f8", version = "=0.1.0" }
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "ecf0f57a20bf229d85f8c19e2a1c198c8de30527", 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" }
+20 -21
View File
@@ -314,11 +314,11 @@ impl<'r> Importer<'r> {
/// its entries. Styles the document doesn't have fall back to the generated TOC styles.
pub(super) fn toc_of(&self, top: &[TopLevelNode]) -> Option<designcraft_doc::Toc> {
use designcraft_doc::{TocEntry, TocPageNumber};
let (ts, story) = top.iter().filter(|node| node.kind == TopKind::TocStyle).find_map(|node| {
let ts = crate::xml::from_craft(node.to_el());
let id = ts.get("Self")?;
let (toc, story) = top.iter().filter(|node| node.kind == TopKind::TocStyle).find_map(|node| {
let toc = craft_idml::model::TocStyleValues::from_el(&node.to_el());
let id = toc.self_id.as_deref()?;
let story = top.iter().find(|node| node.kind == TopKind::Story && node.values().get("AppliedTOCStyle") == Some(id))?;
Some((ts, *self.story_ids.get(story.values().self_id()?)?))
Some((toc, *self.story_ids.get(story.values().self_id()?)?))
})?;
// Property children are element text: formatting whitespace around a reference is dropped
// unless the reference as written names a style.
@@ -327,36 +327,35 @@ impl<'r> Importer<'r> {
let known_chars = |r: Option<&str>| {
r.map(|r| self.listed_char_style_ref(r)).filter(|n| n != designcraft_doc::NO_CHAR_STYLE && self.styles.char_style(n).is_some())
};
let entries: Vec<TocEntry> = ts
.elements()
.filter(|e| e.local() == "TOCStyleEntry")
.filter_map(|e| {
let style = names::style_name_in(PARA_BUILTINS, e.get("Name")?);
let entries: Vec<TocEntry> = toc
.entries
.iter()
.filter_map(|entry| {
let style = names::style_name_in(PARA_BUILTINS, entry.style.as_deref()?);
if style.is_empty() || style.chars().count() > 256 {
return None;
}
let level = e.get("Level").and_then(|l| l.trim().parse::<u8>().ok()).unwrap_or(1).clamp(1, 9);
let page_number = match e.get("PageNumberPosition") {
let level = entry.level.unwrap_or(1).clamp(1, 9);
let page_number = match entry.page_number_position.as_deref() {
Some("BeforeEntry") => TocPageNumber::Before,
Some("NoPageNumber") => TocPageNumber::None,
_ => TocPageNumber::After,
};
let separator = e.get("Separator").map(crate::names::toc_separator_in).filter(|s| s != "\t" && s.chars().count() <= 64);
// InDesign writes these as `Properties` children; attributes are read too.
let entry_style = known(e.prop("FormatStyle").as_deref()).filter(|n| *n != format!("TOC Level {level}"));
let page_number_style = known_chars(e.prop("PageNumberStyle").as_deref());
let separator_style = known_chars(e.prop("SeparatorStyle").as_deref());
let sort = e.get("Sort").is_some_and(|v| v.trim() == "true");
let separator = entry.separator.as_deref().map(crate::names::toc_separator_in).filter(|s| s != "\t" && s.chars().count() <= 64);
// InDesign writes these as `Properties` children; the shared parser accepts both spellings.
let entry_style = known(entry.entry_style.as_deref()).filter(|n| *n != format!("TOC Level {level}"));
let page_number_style = known_chars(entry.page_number_style.as_deref());
let separator_style = known_chars(entry.separator_style.as_deref());
let sort = entry.sort == Some(true);
Some(TocEntry { style, level, entry_style, page_number, separator, page_number_style, separator_style, sort })
})
.take(64)
.collect();
if entries.is_empty() {
return None;
}
let title: String = ts.get("Title").unwrap_or("").chars().filter(|c| !matches!(c, '\n' | '\r' | '\u{2029}')).take(1024).collect();
let title_style = known(ts.get("TitleStyle")).filter(|n| n != "TOC Title");
let create_bookmarks = ts.get("CreateBookmarks").or_else(|| ts.get("CreatePdfBookmarks")) == Some("true");
let title: String = toc.title.as_deref().unwrap_or("").chars().filter(|c| !matches!(c, '\n' | '\r' | '\u{2029}')).take(1024).collect();
let title_style = known(toc.title_style.as_deref()).filter(|n| n != "TOC Title");
let create_bookmarks = toc.create_bookmarks == Some(true);
Some(designcraft_doc::Toc { story, title, entries, page_numbers: true, title_style, create_bookmarks })
}
}