mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 14:22:39 +00:00
Use shared IDML document tree for import
This commit is contained in:
9 files changed
+131
-112
No files matched your search
Generated
+26
-26
@@ -1242,10 +1242,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-idml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=121bd72ba#121bd72ba6a12c5b53da8acd2b3d95bd3c9c664d"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=cbd672594#cbd672594eedcbb95624735e5c9f473720faf591"
|
||||
dependencies = [
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=121bd72ba)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=121bd72ba)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"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=121bd72ba#121bd72ba6a12c5b53da8acd2b3d95bd3c9c664d"
|
||||
dependencies = [
|
||||
"quick-xml 0.41.0",
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
@@ -1680,6 +1671,15 @@ dependencies = [
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=cbd672594#cbd672594eedcbb95624735e5c9f473720faf591"
|
||||
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=121bd72ba#121bd72ba6a12c5b53da8acd2b3d95bd3c9c664d"
|
||||
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=cbd672594#cbd672594eedcbb95624735e5c9f473720faf591"
|
||||
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=121bd72ba)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"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=121bd72ba)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"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=121bd72ba)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"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=121bd72ba)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cbd672594)",
|
||||
"craft-rtf",
|
||||
"craft-wordmodel",
|
||||
"craft-xlsx",
|
||||
|
||||
+2
-2
@@ -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 = "121bd72ba", version = "=0.1.0" }
|
||||
craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "cbd672594", 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 = "121bd72ba", version = "=0.1.0" }
|
||||
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "cbd672594", 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" }
|
||||
|
||||
+69
-56
@@ -3,6 +3,7 @@
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use craft_idml::model::{TopLevelKind as TopKind, TopLevelNode};
|
||||
use designcraft_color::cms::lab;
|
||||
use designcraft_color::{Color, ColorType, Gradient, GradientKind, GradientStop, Swatch, SwatchValue, swatch};
|
||||
use designcraft_doc::{
|
||||
@@ -40,6 +41,14 @@ pub(crate) use package::{percent_decode, uri_to_path};
|
||||
use text_attrs::mojikumi_row;
|
||||
use values::{nums, xmp_date};
|
||||
|
||||
fn top_el(node: &TopLevelNode) -> El {
|
||||
crate::xml::from_craft(node.to_el())
|
||||
}
|
||||
|
||||
fn top_els_of(top: &[TopLevelNode], kind: TopKind) -> impl Iterator<Item = El> + '_ {
|
||||
top.iter().filter(move |node| node.kind == kind).map(top_el)
|
||||
}
|
||||
|
||||
/// Import an IDML package without reading its linked images from disk: this crate never touches
|
||||
/// the file system, so a caller that wants the links brings its own reader
|
||||
/// ([`import_idml_with`]). The engine passes one that checks the automation roots.
|
||||
@@ -79,8 +88,8 @@ pub fn import_idml_report_with_previews(
|
||||
) -> Result<Imported> {
|
||||
let mut pkg = Package::open(bytes)?;
|
||||
let package = pkg.document()?;
|
||||
let root = crate::xml::from_craft(package.root);
|
||||
let top: Vec<El> = package.top.into_iter().map(crate::xml::from_craft).collect();
|
||||
let root = package.root;
|
||||
let top = package.top;
|
||||
let mut warnings = package.warnings;
|
||||
let mut im = Importer::new(read_link, previews);
|
||||
if let Some(m) = package.metadata {
|
||||
@@ -325,17 +334,18 @@ impl<'r> Importer<'r> {
|
||||
self.next_id
|
||||
}
|
||||
|
||||
fn read_preferences(&mut self, top: &[El]) {
|
||||
fn read_preferences(&mut self, top: &[TopLevelNode]) {
|
||||
// Preferences first (page size, facing pages).
|
||||
for e in top {
|
||||
match e.local() {
|
||||
"DocumentPreference" => self.doc_prefs(e),
|
||||
"TransparencyPreference" => {
|
||||
for node in top {
|
||||
let e = top_el(node);
|
||||
match node.kind {
|
||||
TopKind::DocumentPreference => self.doc_prefs(&e),
|
||||
TopKind::TransparencyPreference => {
|
||||
if let Some(v) = e.get("BlendingSpace") {
|
||||
self.settings.blend_space = if v == "RGB" { designcraft_doc::BlendSpace::Rgb } else { designcraft_doc::BlendSpace::Cmyk };
|
||||
}
|
||||
}
|
||||
"TextPreference" => {
|
||||
TopKind::TextPreference => {
|
||||
let a = &mut self.settings.advanced_type;
|
||||
for (k, v) in [
|
||||
("SuperscriptSize", &mut a.superscript_size),
|
||||
@@ -348,11 +358,11 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
}
|
||||
"MarginPreference" => {
|
||||
let (m, c) = margins_of_el(e);
|
||||
TopKind::MarginPreference => {
|
||||
let (m, c) = margins_of_el(&e);
|
||||
self.default_margins = Some((m, c));
|
||||
}
|
||||
"ViewPreference" => {
|
||||
TopKind::ViewPreference => {
|
||||
for (attr, ruler) in [("HorizontalMeasurementUnits", "horizontal"), ("VerticalMeasurementUnits", "vertical")] {
|
||||
let Some(u) = e.get(attr) else { continue };
|
||||
let unit = names::unit_in(u).unwrap_or_else(|| {
|
||||
@@ -375,8 +385,8 @@ impl<'r> Importer<'r> {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
"GridPreference" => self.grid_prefs(e),
|
||||
"PasteboardPreference" => {
|
||||
TopKind::GridPreference => self.grid_prefs(&e),
|
||||
TopKind::PasteboardPreference => {
|
||||
if let Some(v) = e.get("PasteboardMargins").map(nums)
|
||||
&& v.len() == 2
|
||||
&& v[0] >= 0.0
|
||||
@@ -390,8 +400,8 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_composite_fonts(&mut self, top: &[El]) {
|
||||
for e in top.iter().filter(|e| e.local() == "CompositeFont") {
|
||||
fn read_composite_fonts(&mut self, top: &[TopLevelNode]) {
|
||||
for e in top_els_of(top, TopKind::CompositeFont) {
|
||||
let name =
|
||||
e.get("Name").map(str::to_string).unwrap_or_else(|| unescape_id(e.get("Self").unwrap_or("").trim_start_matches("CompositeFont/")));
|
||||
if let Some(id) = e.get("Self") {
|
||||
@@ -417,8 +427,8 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_cjk_tables(&mut self, top: &[El]) -> Result<()> {
|
||||
for e in top.iter().filter(|e| e.local() == "KinsokuTable") {
|
||||
fn read_cjk_tables(&mut self, top: &[TopLevelNode]) -> Result<()> {
|
||||
for e in top_els_of(top, TopKind::KinsokuTable) {
|
||||
if e.get("CantBeginLineChars").is_some() || e.get("CantEndLineChars").is_some() {
|
||||
self.kinsoku.insert(
|
||||
e.get("Self").unwrap_or("").into(),
|
||||
@@ -432,7 +442,7 @@ impl<'r> Importer<'r> {
|
||||
);
|
||||
}
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "MojikumiTable") {
|
||||
for e in top_els_of(top, TopKind::MojikumiTable) {
|
||||
if let (Some(id), Some(name)) = (e.get("Self"), e.get("Name")) {
|
||||
self.mojikumi_names.insert(id.into(), format!("MojikumiTable/{}", unescape_id(name)));
|
||||
}
|
||||
@@ -450,19 +460,19 @@ impl<'r> Importer<'r> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(&mut self, _root: &El, top: &[El]) -> Result<()> {
|
||||
fn run(&mut self, _root: &craft_idml::model::Values, top: &[TopLevelNode]) -> Result<()> {
|
||||
self.read_preferences(top);
|
||||
self.read_composite_fonts(top);
|
||||
self.read_cjk_tables(top)?;
|
||||
self.graphics(top);
|
||||
self.styles(top);
|
||||
if let Some(e) = top.iter().find(|e| e.local() == "FootnoteOption") {
|
||||
self.footnote_option(e);
|
||||
if let Some(e) = top_els_of(top, TopKind::FootnoteOption).next() {
|
||||
self.footnote_option(&e);
|
||||
}
|
||||
if let Some(e) = top.iter().find(|e| e.local() == "EPubExportPreference") {
|
||||
self.epub_split(e);
|
||||
if let Some(e) = top_els_of(top, TopKind::EpubExportPreference).next() {
|
||||
self.epub_split(&e);
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "Layer") {
|
||||
for e in top_els_of(top, TopKind::Layer) {
|
||||
let id = LayerId(self.alloc());
|
||||
let color = match e.prop_el("LayerColor") {
|
||||
Some(c) if c.get("type") == Some("list") => {
|
||||
@@ -501,33 +511,34 @@ impl<'r> Importer<'r> {
|
||||
suppress_wrap_when_hidden: false,
|
||||
});
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "CrossReferenceFormat") {
|
||||
self.xref_format(e);
|
||||
for e in top_els_of(top, TopKind::CrossReferenceFormat) {
|
||||
self.xref_format(&e);
|
||||
}
|
||||
self.read_hyperlinks(top);
|
||||
if let Some(ix) = top.iter().find(|e| e.local() == "Index") {
|
||||
self.index_topics_of(ix, &IndexTopic::default());
|
||||
if let Some(ix) = top_els_of(top, TopKind::Index).next() {
|
||||
self.index_topics_of(&ix, &IndexTopic::default());
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "TextVariable") {
|
||||
self.text_variable(e);
|
||||
for e in top_els_of(top, TopKind::TextVariable) {
|
||||
self.text_variable(&e);
|
||||
}
|
||||
// Stories (ids first so frames can reference them).
|
||||
let mut pending_stories = Vec::new();
|
||||
for e in top.iter().filter(|e| e.local() == "Story") {
|
||||
for node in top.iter().filter(|node| node.kind == TopKind::Story) {
|
||||
let Some(source) = node.story() else { continue };
|
||||
let id = StoryId(self.alloc());
|
||||
if let Some(s) = e.get("Self") {
|
||||
if let Some(s) = source.values.self_id() {
|
||||
self.story_ids.insert(s.to_string(), id);
|
||||
}
|
||||
pending_stories.push((id, e));
|
||||
pending_stories.push((id, source.clone()));
|
||||
}
|
||||
for (id, e) in pending_stories {
|
||||
let story = self.story(id, e);
|
||||
for (id, source) in pending_stories {
|
||||
let story = self.story_from_model(id, source, ParaFormat::default());
|
||||
self.stories.insert(id, story);
|
||||
}
|
||||
self.toc = self.toc_of(top);
|
||||
self.place_index_xrefs();
|
||||
// Cross-references point at their hyperlink's destination.
|
||||
for h in top.iter().filter(|e| e.local() == "Hyperlink") {
|
||||
for h in top_els_of(top, TopKind::Hyperlink) {
|
||||
let (Some(src), Some(dest)) = (h.get("Source"), h.prop("Destination")) else { continue };
|
||||
let (Some(&(sid, k)), Some(&target)) = (self.xref_srcs.get(src), self.anchor_ids.get(dest.trim())) else { continue };
|
||||
if let Some(x) = self.stories.get_mut(&sid).and_then(|st| st.xrefs.get_mut(k)) {
|
||||
@@ -535,27 +546,28 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
// Parent spreads: ids first (pages reference other parents).
|
||||
let masters: Vec<&El> = top.iter().filter(|e| e.local() == "MasterSpread").collect();
|
||||
let masters: Vec<craft_idml::model::Spread> =
|
||||
top.iter().filter(|node| node.kind == TopKind::MasterSpread).filter_map(|node| node.spread().cloned()).collect();
|
||||
let mut master_ids = Vec::new();
|
||||
for m in &masters {
|
||||
let id = SpreadId(self.alloc());
|
||||
if let Some(s) = m.get("Self") {
|
||||
if let Some(s) = m.values.self_id() {
|
||||
self.parent_ids.insert(s.to_string(), id);
|
||||
}
|
||||
master_ids.push(id);
|
||||
}
|
||||
for (m, id) in masters.iter().zip(master_ids) {
|
||||
let sp = self.spread(m, id, true);
|
||||
let sp = self.spread_from_model(m, id, true);
|
||||
self.parents.push(sp);
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "Spread") {
|
||||
for model_spread in top.iter().filter(|node| node.kind == TopKind::Spread).filter_map(TopLevelNode::spread) {
|
||||
let id = SpreadId(self.alloc());
|
||||
let sp = self.spread(e, id, false);
|
||||
let sp = self.spread_from_model(model_spread, id, false);
|
||||
self.spreads.push(sp);
|
||||
}
|
||||
// Sections. A section whose AlternateLayout differs from the one before starts that layout.
|
||||
let mut last_layout: Option<String> = None;
|
||||
for e in top.iter().filter(|e| e.local() == "Section") {
|
||||
for e in top_els_of(top, TopKind::Section) {
|
||||
let Some(start) = e.get("PageStart").and_then(|p| self.page_index.get(p)).copied() else { continue };
|
||||
let layout = e.get("AlternateLayout").map(str::trim).filter(|l| !l.is_empty()).map(str::to_string);
|
||||
let starts_layout = layout.clone().filter(|l| last_layout.as_ref() != Some(l));
|
||||
@@ -601,35 +613,36 @@ impl<'r> Importer<'r> {
|
||||
/// Hyperlink sources, destinations and the `Hyperlink` elements that join them (#1446), by
|
||||
/// name: the pages, page items and anchors they name are read later, so `finish` puts the two
|
||||
/// ends together.
|
||||
fn read_hyperlinks(&mut self, top: &[El]) {
|
||||
for e in top {
|
||||
fn read_hyperlinks(&mut self, top: &[TopLevelNode]) {
|
||||
for node in top {
|
||||
let e = top_el(node);
|
||||
let me = || e.get("Self").unwrap_or("").trim().to_string();
|
||||
match e.local() {
|
||||
"HyperlinkURLDestination" => {
|
||||
if let Some(u) = attr_or_prop(e, "DestinationURL") {
|
||||
match node.kind {
|
||||
TopKind::HyperlinkUrlDestination => {
|
||||
if let Some(u) = attr_or_prop(&e, "DestinationURL") {
|
||||
self.link_dests.insert(me(), PendingDest::Url(u));
|
||||
}
|
||||
}
|
||||
"HyperlinkPageDestination" => {
|
||||
if let Some(pg) = attr_or_prop(e, "DestinationPage") {
|
||||
TopKind::HyperlinkPageDestination => {
|
||||
if let Some(pg) = attr_or_prop(&e, "DestinationPage") {
|
||||
self.link_dests.insert(me(), PendingDest::Page(pg));
|
||||
}
|
||||
}
|
||||
"HyperlinkPageItemSource" => {
|
||||
if let Some(it) = attr_or_prop(e, "SourcePageItem") {
|
||||
TopKind::HyperlinkPageItemSource => {
|
||||
if let Some(it) = attr_or_prop(&e, "SourcePageItem") {
|
||||
self.link_item_srcs.insert(me(), it);
|
||||
}
|
||||
}
|
||||
"Hyperlink" => {
|
||||
if let (Some(src), Some(dest)) = (attr_or_prop(e, "Source"), attr_or_prop(e, "Destination")) {
|
||||
TopKind::Hyperlink => {
|
||||
if let (Some(src), Some(dest)) = (attr_or_prop(&e, "Source"), attr_or_prop(&e, "Destination")) {
|
||||
let name = e.get("Name").unwrap_or("").trim().to_string();
|
||||
self.links.push((name, src, dest));
|
||||
}
|
||||
}
|
||||
// A destination kind this importer does not read (an external page, say): kept
|
||||
// by name so a link dropped for it can say what it led to.
|
||||
other if other.starts_with("Hyperlink") && other.ends_with("Destination") => {
|
||||
self.other_dests.insert(me(), other.to_string());
|
||||
TopKind::HyperlinkOtherDestination => {
|
||||
self.other_dests.insert(me(), e.local().to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -740,7 +753,7 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
|
||||
/// The finished document, and the warnings raised while finishing it.
|
||||
fn finish(mut self, root: &El) -> Result<(Document, Vec<String>)> {
|
||||
fn finish(mut self, root: &craft_idml::model::Values) -> Result<(Document, Vec<String>)> {
|
||||
let title = root.get("Name").map(|n| n.trim_end_matches(".indd").to_string()).filter(|n| !n.is_empty()).unwrap_or_else(|| "Untitled".into());
|
||||
if self.spreads.is_empty() {
|
||||
return Err(IdmlError::Invalid("document has no spreads".into()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::values::tint;
|
||||
use super::{BaselineGrid, El, GridRelative, Importer, PARA_BUILTINS, names};
|
||||
use super::{BaselineGrid, El, GridRelative, Importer, PARA_BUILTINS, TopKind, TopLevelNode, names};
|
||||
|
||||
/// IDML stores a sort key on each topic, rather than on its page references.
|
||||
#[derive(Clone, Default)]
|
||||
@@ -312,12 +312,13 @@ impl<'r> Importer<'r> {
|
||||
|
||||
/// The table of contents: the TOC style a story is generated from (`AppliedTOCStyle`), with
|
||||
/// its entries. Styles the document doesn't have fall back to the generated TOC styles.
|
||||
pub(super) fn toc_of(&self, top: &[El]) -> Option<designcraft_doc::Toc> {
|
||||
pub(super) fn toc_of(&self, top: &[TopLevelNode]) -> Option<designcraft_doc::Toc> {
|
||||
use designcraft_doc::{TocEntry, TocPageNumber};
|
||||
let (ts, story) = top.iter().filter(|e| e.local() == "TOCStyle").find_map(|ts| {
|
||||
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 story = top.iter().find(|e| e.local() == "Story" && e.get("AppliedTOCStyle") == Some(id))?;
|
||||
Some((ts, *self.story_ids.get(story.get("Self")?)?))
|
||||
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()?)?))
|
||||
})?;
|
||||
// Property children are element text: formatting whitespace around a reference is dropped
|
||||
// unless the reference as written names a style.
|
||||
|
||||
@@ -11,8 +11,8 @@ impl<'a> Package<'a> {
|
||||
}
|
||||
|
||||
/// Reads the designmap, XML parts, included resources and metadata with the shared parser.
|
||||
pub(super) fn document(&mut self) -> Result<craft_idml::Document> {
|
||||
self.inner.document().map_err(|e| match e {
|
||||
pub(super) fn document(&mut self) -> Result<craft_idml::model::ModelDocument> {
|
||||
self.inner.document().map(craft_idml::model::ModelDocument::from_package).map_err(|e| match e {
|
||||
craft_idml::Error::TooLarge { part, limit } => IdmlError::Part { part, msg: format!("larger than the {limit}-byte package read limit") },
|
||||
craft_idml::Error::Part { part, msg } => IdmlError::Part { part, msg },
|
||||
other => IdmlError::NotIdml(other.to_string()),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::frame::{fit_columns, margins_of};
|
||||
use super::{
|
||||
Affine, Arc, Columns, El, Guide, Importer, ItemId, Margins, Orientation, Page, PageId, PageSide, ParentInfo, Point, Rect, Spread, SpreadId, names,
|
||||
Affine, Arc, Columns, Guide, Importer, ItemId, Margins, Orientation, Page, PageId, PageSide, ParentInfo, Point, Rect, Spread, SpreadId, names,
|
||||
};
|
||||
|
||||
impl<'r> Importer<'r> {
|
||||
@@ -82,11 +82,10 @@ impl<'r> Importer<'r> {
|
||||
(margins, columns, local_margins)
|
||||
}
|
||||
|
||||
pub(super) fn spread(&mut self, e: &El, id: SpreadId, master: bool) -> Spread {
|
||||
let model_spread = craft_idml::model::Spread::from_el(&crate::xml::to_craft(e));
|
||||
pub(super) fn spread_from_model(&mut self, model_spread: &craft_idml::model::Spread, id: SpreadId, master: bool) -> Spread {
|
||||
let facing = self.settings.facing_pages;
|
||||
// Page rectangles in IDML spread coordinates.
|
||||
let pages = self.page_rects(&model_spread);
|
||||
let pages = self.page_rects(model_spread);
|
||||
let min_x = pages.iter().map(|(r, _)| r.x0).fold(f64::INFINITY, f64::min);
|
||||
let min_y = pages.iter().map(|(r, _)| r.y0).fold(f64::INFINITY, f64::min);
|
||||
let (min_x, min_y) = if min_x.is_finite() { (min_x, min_y) } else { (0.0, 0.0) };
|
||||
@@ -135,8 +134,9 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
let overrides: Vec<Vec<String>> = pages.iter().map(|(_, p)| p.override_list().into_iter().map(str::to_string).collect()).collect();
|
||||
let mut items = Vec::new();
|
||||
for c in e.elements() {
|
||||
if let Some(it) = self.item(c, shift) {
|
||||
for item in model_spread.items() {
|
||||
let item_el = crate::xml::from_craft(item.to_el());
|
||||
if let Some(it) = self.item(&item_el, shift) {
|
||||
items.push(Arc::new(it));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ impl<'r> Importer<'r> {
|
||||
|
||||
pub(super) fn story_with_para(&mut self, id: StoryId, e: &El, default_para: ParaFormat) -> Story {
|
||||
let source = craft_idml::model::Story::from_el(&crate::xml::to_craft(e));
|
||||
self.story_from_model(id, source, default_para)
|
||||
}
|
||||
|
||||
pub(super) fn story_from_model(&mut self, id: StoryId, source: craft_idml::model::Story, default_para: ParaFormat) -> Story {
|
||||
let mut b = StoryBuilder {
|
||||
text: String::new(),
|
||||
paras: vec![default_para.clone()],
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
use super::table::uniform_cell_stroke;
|
||||
use super::values::tint;
|
||||
use super::{
|
||||
CHAR_BUILTINS, CharacterStyle, El, Fill, Importer, OBJECT_BUILTINS, ObjectStyle, PARA_BUILTINS, ParagraphStyle, Rule, names, st, swatch,
|
||||
unescape_id,
|
||||
CHAR_BUILTINS, CharacterStyle, El, Fill, Importer, OBJECT_BUILTINS, ObjectStyle, PARA_BUILTINS, ParagraphStyle, Rule, TopKind, TopLevelNode,
|
||||
names, st, swatch, top_el, unescape_id,
|
||||
};
|
||||
|
||||
type StyleElements = (Vec<(String, El)>, Vec<(String, El)>, Vec<(String, El)>, Vec<(String, El)>, Vec<(String, El)>);
|
||||
|
||||
fn style_elements(top: &[El]) -> StyleElements {
|
||||
fn style_elements(top: &[TopLevelNode]) -> StyleElements {
|
||||
let mut paras = Vec::new();
|
||||
let mut chars = Vec::new();
|
||||
let mut objects = Vec::new();
|
||||
let mut cell_styles = Vec::new();
|
||||
let mut table_styles = Vec::new();
|
||||
for group in top.iter().filter_map(|el| craft_idml::model::StyleGroup::from_el(&crate::xml::to_craft(el))) {
|
||||
let model_top: Vec<_> = top.iter().map(TopLevelNode::to_el).collect();
|
||||
for group in model_top.iter().filter_map(craft_idml::model::StyleGroup::from_el) {
|
||||
for (_, style) in group.styles() {
|
||||
let id = style.values.self_id().unwrap_or("").to_string();
|
||||
let el = crate::xml::from_craft(style.to_el());
|
||||
@@ -32,8 +33,8 @@ fn style_elements(top: &[El]) -> StyleElements {
|
||||
impl<'r> Importer<'r> {
|
||||
// ---------- styles ----------
|
||||
|
||||
pub(super) fn styles(&mut self, top: &[El]) {
|
||||
for e in top.iter().filter(|e| e.local() == "Condition") {
|
||||
pub(super) fn styles(&mut self, top: &[TopLevelNode]) {
|
||||
for e in top.iter().filter(|node| node.kind == TopKind::Condition).map(top_el) {
|
||||
let (Some(id), Some(name)) = (e.get("Self"), e.get("Name")) else { continue };
|
||||
// Indicator colours: "r g b" (0–255) or a UI colour name (kept as the default blue).
|
||||
let nums: Vec<u8> = e
|
||||
@@ -47,7 +48,7 @@ impl<'r> Importer<'r> {
|
||||
self.condition_names.insert(id.to_string(), name.to_string());
|
||||
self.conditions.push(designcraft_doc::Condition { name: name.to_string(), color, visible: e.get("Visible") != Some("false") });
|
||||
}
|
||||
for e in top.iter().filter(|e| e.local() == "NumberingList") {
|
||||
for e in top.iter().filter(|node| node.kind == TopKind::NumberingList).map(top_el) {
|
||||
let name = e.get("Name").unwrap_or("").to_string();
|
||||
if !name.is_empty() && !name.starts_with("$ID/") && !self.lists.iter().any(|l| l.name == name) {
|
||||
self.lists
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::frame::{Prefs, text_frame_options};
|
||||
use super::values::lab_to_color;
|
||||
use super::{
|
||||
Color, ColorType, El, Gradient, GradientKind, GradientStop, HashMap, HashSet, Importer, Styles, Swatch, SwatchValue, TextFrameOptions, names,
|
||||
swatch,
|
||||
Color, ColorType, El, Gradient, GradientKind, GradientStop, HashMap, HashSet, Importer, Styles, Swatch, SwatchValue, TextFrameOptions,
|
||||
TopLevelNode, names, swatch,
|
||||
};
|
||||
|
||||
impl<'r> Importer<'r> {
|
||||
@@ -30,8 +30,8 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
|
||||
/// Custom stroke styles.
|
||||
fn read_stroke_styles(&mut self, top: &[El]) {
|
||||
let top: Vec<_> = top.iter().map(crate::xml::to_craft).collect();
|
||||
fn read_stroke_styles(&mut self, top: &[TopLevelNode]) {
|
||||
let top: Vec<_> = top.iter().map(TopLevelNode::to_el).collect();
|
||||
for e in craft_idml::model::stroke_styles(&top) {
|
||||
let (Some(id), Some(name)) = (e.values.self_id(), e.values.name()) else { continue };
|
||||
let kind = match e.kind {
|
||||
@@ -47,8 +47,8 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
|
||||
/// Ink Manager settings: inks converted to process and ink aliases.
|
||||
fn read_inks(&mut self, top: &[El]) {
|
||||
let model_top: Vec<_> = top.iter().map(crate::xml::to_craft).collect();
|
||||
fn read_inks(&mut self, top: &[TopLevelNode]) {
|
||||
let model_top: Vec<_> = top.iter().map(TopLevelNode::to_el).collect();
|
||||
for e in craft_idml::model::inks(&model_top) {
|
||||
let Some(name) =
|
||||
e.name().filter(|n| !n.starts_with("$ID/") && !["Process Cyan", "Process Magenta", "Process Yellow", "Process Black"].contains(n))
|
||||
@@ -64,8 +64,8 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn graphics(&mut self, top: &[El]) {
|
||||
let model_top: Vec<_> = top.iter().map(crate::xml::to_craft).collect();
|
||||
pub(super) fn graphics(&mut self, top: &[TopLevelNode]) {
|
||||
let model_top: Vec<_> = top.iter().map(TopLevelNode::to_el).collect();
|
||||
let swatches = craft_idml::model::swatches(&model_top);
|
||||
let mut order: Vec<(String, Swatch)> = Vec::new();
|
||||
// Colours.
|
||||
|
||||
Reference in new issue
Block a user