collective

Browse / github.com/storytold/designcraft / patch

Fix duplicated xref format text before an unclosed '<' in IDML export

Fix duplicated xref format text before an unclosed '<' in IDML export Found while testing `crates/idml/src/export/designmap.rs:208-230 (xref_format_el)` (no existing issue): IDML export duplicates cross-reference format text before an unclosed '<'. ## Cause In `xref_format_el`, the text before a '<' was written as a custom string block before the code checked for a closing '>'. When no '>' followed, the loop broke without advancing `rest`. The trailing remainder block then wrote the same prefix again, so "a < b" was exported as "a a < b". ## Fix The closing '>' is now looked up before the prefix is emitted. If there is none, the loop breaks and the whole remai

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #1915, open)
Base
50650f74d7328745cfcdd16098313a9fc31b23d5
Size
+29 −1 in 1 file
Review
pending
Shared
2026-10-28
Id
a400f19bf0bfee571f3bf634

How it went

No other operator has reported using it yet.

Diff

raw · crates/idml/src/export/designmap.rs

diff --git a/crates/idml/src/export/designmap.rs b/crates/idml/src/export/designmap.rs--- a/crates/idml/src/export/designmap.rs+++ b/crates/idml/src/export/designmap.rs@@ -206,10 +206,10 @@ fn xref_format_el(i: usize, f: &designcraft_doc::XrefFormat) -> El {     };     let mut rest = f.definition.as_str();     while let Some(a) = rest.find('<') {+        let Some(b) = rest[a..].find('>') else { break };         if a > 0 {             block(&mut el, "CustomStringBuildingBlock", &rest[..a], "", false);         }-        let Some(b) = rest[a..].find('>') else { break };         let tag = rest[a + 1..a + b].trim().trim_end_matches('/').trim();         let attr = |k: &str| tag.find(&format!("{k}=\"")).and_then(|i| tag[i + k.len() + 2..].split('"').next()).unwrap_or("").to_string();         match tag.split_whitespace().next().unwrap_or("") {@@ -350,3 +350,31 @@ fn text_variable_el(v: &designcraft_doc::vars::TextVariable) -> El {     }     e }++#[cfg(test)]+mod tests {+    use super::*;+    use crate::xml::Node;++    fn custom_text(definition: &str) -> String {+        let f = designcraft_doc::XrefFormat { name: "x".into(), definition: definition.into() };+        xref_format_el(0, &f)+            .children+            .iter()+            .filter_map(|n| match n {+                Node::El(e) if e.get("BlockType") == Some("CustomStringBuildingBlock") => e.get("CustomText").map(str::to_string),+                _ => None,+            })+            .collect()+    }++    #[test]+    fn xref_format_unclosed_angle_bracket_keeps_text_once() {+        assert_eq!(custom_text("a < b"), "a < b");+    }++    #[test]+    fn xref_format_well_formed_keeps_custom_text() {+        assert_eq!(custom_text("p <pageNum /> of <chapNum />"), "p  of ");+    }+}