From 50b5936b78cbcdfb56bc12968f353659d2d12d51 Mon Sep 17 00:00:00 2001 From: Henrique Cabral Date: Wed, 28 Oct 2026 21:07:42 -0400 Subject: [PATCH] IDML export: write the document's default StoryPreference InDesign always writes a document-level StoryPreference in Resources/Preferences.xml; DesignCraft only wrote one per story. IDML readers that take the spread reading order from the document's preference, such as Okapi's IDML filter, failed on DesignCraft's files without it. Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 1 + crates/idml/src/export/fonts_prefs.rs | 10 ++++++++++ crates/idml/src/tests.rs | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index c02176bab..7070bb62a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -380,6 +380,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m Newest first. +- **2026-10-28** · IDML export writes the document's default `StoryPreference` in `Resources/Preferences.xml`, as InDesign does. Only each story carried one, and IDML readers that take the spread reading order from the document's (Okapi's IDML filter) failed on DesignCraft's files. No readiness percentage change. - **2026-10-27** · An iconic panel's flyout stays open while you work in the canvas or a text field: Auto-Collapse Iconic Panels is off by default, and preferences saved with it on start with it off. Preferences › Interface › Panels holds the setting next to the column bar's menu item. No readiness percentage change. - **2026-10-24** · Column rules run from the top line's ascent to the bottom line's descent, as InDesign draws them, instead of from the top to the bottom of the columns, on screen, in PDF and in PowerPoint export. The top and bottom insets shorten the rule from those lines. Existing documents draw their column rules at the new length. No readiness percentage change. - **2026-10-20** · Edit › Keyboard Shortcuts is craft-keymap's shared dialog: commands grouped by menu with Show and Filter, recording that asks before taking a key from another command, undo and redo, named shortcut sets (edits of Default become Custom; an imported set becomes a set of its own), an on-screen US keyboard, InDesign Show Set files reviewed before they apply, JSON export and an HTML summary. ui.json keeps the `shortcuts` map earlier versions read, for the active set. No readiness percentage change. diff --git a/crates/idml/src/export/fonts_prefs.rs b/crates/idml/src/export/fonts_prefs.rs index fac86af33..2e8daa565 100644 --- a/crates/idml/src/export/fonts_prefs.rs +++ b/crates/idml/src/export/fonts_prefs.rs @@ -169,6 +169,16 @@ impl<'a> Ex<'a> { .attr("SubscriptSize", num(a.subscript_size)) .attr("SubscriptPosition", num(a.subscript_position)), ); + // InDesign always writes the document's default story preference; readers such as Okapi's IDML + // filter take the spread reading order from it and fail without it. + root.push( + El::new("StoryPreference") + .attr("OpticalMarginAlignment", "false") + .attr("OpticalMarginSize", "12") + .attr("FrameType", "TextFrameType") + .attr("StoryOrientation", "Horizontal") + .attr("StoryDirection", "LeftToRightDirection"), + ); document(&root) } } diff --git a/crates/idml/src/tests.rs b/crates/idml/src/tests.rs index 0d078c63c..b5b5a1cd8 100644 --- a/crates/idml/src/tests.rs +++ b/crates/idml/src/tests.rs @@ -554,6 +554,14 @@ fn basic_paragraph_is_normal_paragraph_style() { assert_eq!(back.styles.paragraph.iter().filter(|p| p.name == st::BASIC_PARAGRAPH).count(), 1); } +/// Like InDesign, the export carries the document's default story preference, which IDML readers expect. +#[test] +fn export_writes_the_document_story_preference() { + let d = import_idml_with(&fixture(), &|_| None).unwrap(); + let prefs = zip_text(&export_idml(&d), "Resources/Preferences.xml"); + assert!(prefs.contains(r#""#), "{prefs}"); +} + /// Page items, frames, tables and preferences an IDML file leaves unset are InDesign's defaults /// for a new document. #[test]