From dab41a4f60defb2c487c0740eb4c673da468ca1c Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 09:35:55 -0500 Subject: [PATCH] Use shared IDML hyperlink destination writer --- Cargo.lock | 46 ++++++++++++++--------------- Cargo.toml | 4 +-- crates/idml/src/export/common.rs | 4 --- crates/idml/src/export/designmap.rs | 6 ++-- crates/idml/src/export/story.rs | 10 ++----- 5 files changed, 30 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 803dba853..aacb7a702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,20 +1242,20 @@ dependencies = [ [[package]] name = "craft-idml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" +source = "git+https://github.com/storytold/craft-libs?rev=33e1fffca#33e1fffcace339b5a046a3b6822d7c1a0f545b4c" dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=33e1fffca)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=33e1fffca)", "thiserror 2.0.21", ] [[package]] name = "craft-idml" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1#ff0cbc3a137fac332b29a50fc1f5b954143ccc9c" +source = "git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558#eed3c28cf016723d004d6f2c79c61424c15d4558" dependencies = [ - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1)", - "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", + "craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=eed3c28cf016723d004d6f2c79c61424c15d4558)", "thiserror 2.0.21", ] @@ -1644,6 +1644,15 @@ dependencies = [ "thiserror 2.0.21", ] +[[package]] +name = "craft-xml" +version = "0.1.0" +source = "git+https://github.com/storytold/craft-libs?rev=33e1fffca#33e1fffcace339b5a046a3b6822d7c1a0f545b4c" +dependencies = [ + "quick-xml 0.41.0", + "thiserror 2.0.21", +] + [[package]] name = "craft-xml" version = "0.1.0" @@ -1709,12 +1718,13 @@ dependencies = [ ] [[package]] -name = "craft-xml" +name = "craft-zip" version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1#ff0cbc3a137fac332b29a50fc1f5b954143ccc9c" +source = "git+https://github.com/storytold/craft-libs?rev=33e1fffca#33e1fffcace339b5a046a3b6822d7c1a0f545b4c" dependencies = [ - "quick-xml 0.41.0", + "flate2", "thiserror 2.0.21", + "zip 9.1.1", ] [[package]] @@ -1767,16 +1777,6 @@ dependencies = [ "zip 9.1.1", ] -[[package]] -name = "craft-zip" -version = "0.1.0" -source = "git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1#ff0cbc3a137fac332b29a50fc1f5b954143ccc9c" -dependencies = [ - "flate2", - "thiserror 2.0.21", - "zip 9.1.1", -] - [[package]] name = "crc32fast" version = "1.5.3" @@ -2021,8 +2021,8 @@ 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=33e1fffca)", "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=f23b0f33f0d00b157476533a43cbbcfd901aa1f1)", - "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=ff0cbc3a1)", "designcraft-color", "designcraft-compose", "designcraft-doc", @@ -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=ff0cbc3a1)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=33e1fffca)", "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=ff0cbc3a1)", + "craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=33e1fffca)", "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=ff0cbc3a1)", + "craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=33e1fffca)", "craft-rtf", "craft-wordmodel", "craft-xlsx", diff --git a/Cargo.toml b/Cargo.toml index 245054c36..d24749e18 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 = "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 = "ff0cbc3a1", version = "=0.1.0" } +craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "33e1fffca", 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 = "ff0cbc3a1", version = "=0.1.0" } +craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "33e1fffca", 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/common.rs b/crates/idml/src/export/common.rs index 38500f99e..734a16cc7 100644 --- a/crates/idml/src/export/common.rs +++ b/crates/idml/src/export/common.rs @@ -38,10 +38,6 @@ pub(super) fn affine_s(a: Affine) -> String { a.as_coeffs().iter().map(|v| num(*v)).collect::>().join(" ") } -pub(super) fn anchor_self(id: u64) -> String { - format!("HyperlinkTextDestination/a{id}") -} - pub(super) fn xref_format_self(i: usize) -> String { format!("CrossReferenceFormat/f{i}") } diff --git a/crates/idml/src/export/designmap.rs b/crates/idml/src/export/designmap.rs index 6cc04362b..7544d578c 100644 --- a/crates/idml/src/export/designmap.rs +++ b/crates/idml/src/export/designmap.rs @@ -1,4 +1,4 @@ -use super::common::{anchor_self, bool_s, p, uid, with_props, xref_format_self}; +use super::common::{bool_s, p, uid, with_props, xref_format_self}; use super::{CHAR_BUILTINS, Document, El, Ex, HashSet, PARA_BUILTINS, escape_id, names, num}; impl<'a> Ex<'a> { @@ -165,7 +165,7 @@ impl<'a> Ex<'a> { // deleted names no element, so the file would hold a `Hyperlink` whose // `Destination` points at nothing -- import only warns and InDesign may refuse // the file (noted in review). - De::Anchor(a) => d.find_anchor(*a).map(|_| anchor_self(*a)), + De::Anchor(a) => d.find_anchor(*a).map(|_| craft_idml::model::StoryAnchor::destination_self(*a)), De::Url(u) => Some(self.url_dest_el(&mut root, u, &h.name)), De::Email(e) => Some(self.url_dest_el(&mut root, &format!("mailto:{e}"), &h.name)), De::Page(p) => d.page(*p).map(|pg| { @@ -237,7 +237,7 @@ impl<'a> Ex<'a> { .attr("Hidden", "false") .attr("DestinationUniqueKey", target & 0xFFFF_FFFF); let mut props = El::new("Properties"); - props.push(p("Destination", "object", anchor_self(target))); + props.push(p("Destination", "object", craft_idml::model::StoryAnchor::destination_self(target))); h.push(props); root.push(h); } diff --git a/crates/idml/src/export/story.rs b/crates/idml/src/export/story.rs index d3232e21e..7f590532d 100644 --- a/crates/idml/src/export/story.rs +++ b/crates/idml/src/export/story.rs @@ -1,4 +1,4 @@ -use super::common::{anchor_self, change_type, uid, with_props, xref_format_self}; +use super::common::{change_type, uid, with_props, xref_format_self}; use super::{CHAR_BUILTINS, CharFormat, El, Ex, ListType, NO_CHAR_ID, Node, PARA_BUILTINS, ParaAttrs, ParaFormat, Story, TOC_STYLE_ID, names, st}; impl<'a> Ex<'a> { @@ -342,13 +342,7 @@ impl<'a> Ex<'a> { flush_content(&mut pending, &mut out); let k = s.text[..seg_start + ci].matches(designcraft_doc::ANCHOR_MARK).count(); if let Some(a) = s.anchors.get(k) { - out.push(Node::El( - El::new("HyperlinkTextDestination") - .attr("Self", anchor_self(a.id)) - .attr("Name", &a.name) - .attr("Hidden", "false") - .attr("DestinationUniqueKey", a.id & 0xFFFF_FFFF), - )); + out.push(Node::El(crate::xml::from_craft(craft_idml::model::StoryAnchor::destination_el(a.id, &a.name)))); } } else if ch == designcraft_doc::OBJECT_MARK { // An anchored object: the item inside the range with its anchoring settings.