mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-27 11:46:51 -06:00
fix: IDML links in a subfolder beside the package load on another machine
A package opened away from its author's machine kept image links like `/images/logo.png` that no longer exist; only the package folder and its Links/ folder were searched, so images in `images/` next to the .idml showed as missing. Also try the link's trailing folders (up to 8) under the package folder, longest first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
a930276fd7
commit
0a836edb7d
@@ -360,6 +360,7 @@ Newest first.
|
||||
- **2026-10-14** · The Pathfinder panel is laid out as InDesign's: Paths (Join, Open, Close, Reverse), Pathfinder, Convert Shape and Convert Point, each a row of icon buttons. Join Path closes an open path or joins two at their nearest ends (`path.join`), and Convert Point makes the selected points plain, corner, smooth or symmetrical (`path.convertPoints`). No readiness percentage change.
|
||||
- **2026-10-12** · Linked text files (#597): placed Word, RTF and text files can stay linked; the Links panel shows them OK / Modified / Missing, and Update imports the file again into the same frames with the saved style map (the Links panel asks before replacing edits made in the layout). No readiness percentage change.
|
||||
- **2026-10-15** · IDML: the CJK leading model InDesign writes on [No paragraph style] of every document (Aki Below) only applies when the document uses a Japanese composer, as in InDesign; a Western document's paragraphs after a size change no longer sit lower than in InDesign (Montilla Design's Flex Layout file: its captions came out overset). No readiness percentage change.
|
||||
- **2026-10-15** · IDML: linked images in a subfolder beside the package load when the package is opened on another machine (a link to `/images/logo.png` finds `images/logo.png` next to the .idml); they showed as missing. No readiness percentage change.
|
||||
- **2026-10-14** · Type › Fill with Placeholder Text fills a frame with paragraphs of a few sentences, as InDesign does, so one paragraph can be styled on its own (it was one long paragraph, and the filler ran sentences together, "interit.Ovid"). No readiness percentage change.
|
||||
- **2026-10-13** · Object › Fitting has InDesign's shortcuts: Fill Frame Proportionally ⌘⌥⇧C, Fit Content Proportionally ⌘⌥⇧E, Fit Frame to Content ⌘⌥C, Fit Content to Frame ⌘⌥E, Center Content ⌘⇧E. No readiness percentage change.
|
||||
- **2026-10-13** · Gradients between process colours blend as inks, as InDesign shows them: magenta to cyan passes through C 50 M 50 (a light lilac) on screen instead of the darker RGB mix, and a midpoint between CMYK or grey stops no longer turns the PDF shading RGB. No readiness percentage change.
|
||||
|
||||
@@ -80,6 +80,10 @@ pub fn import_report(bytes: &[u8], dir: Option<&std::path::Path>) -> Result<(Doc
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
const MAX_LINK_PATH_BYTES: usize = 128 * 1024;
|
||||
|
||||
/// How many trailing folders of a link are tried beside the opened package.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
const MAX_LINK_SUFFIX_PARTS: usize = 8;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn packaged_link_candidates(link: &str, dir: Option<&std::path::Path>) -> Vec<std::path::PathBuf> {
|
||||
// Enough for a maximum-length Windows path even with four-byte UTF-8 characters.
|
||||
@@ -103,6 +107,14 @@ fn packaged_link_candidates(link: &str, dir: Option<&std::path::Path>) -> Vec<st
|
||||
candidates.push(dir.join("Links").join(suffix.iter().collect::<std::path::PathBuf>()));
|
||||
}
|
||||
}
|
||||
// A package moved off its author's machine keeps its own subfolders (`/images/logo.png`
|
||||
// beside the .idml as `images/logo.png`): try the link's trailing folders, longest first.
|
||||
let first = parts.len().saturating_sub(MAX_LINK_SUFFIX_PARTS);
|
||||
for start in first..parts.len().saturating_sub(1) {
|
||||
if let Some(suffix) = parts.get(start..).filter(|s| s.iter().all(safe_part)) {
|
||||
candidates.push(dir.join(suffix.iter().collect::<std::path::PathBuf>()));
|
||||
}
|
||||
}
|
||||
if let Some(name) = parts.last().filter(|part| safe_part(part)) {
|
||||
candidates.push(dir.join(name));
|
||||
candidates.push(dir.join("Links").join(name));
|
||||
@@ -208,6 +220,23 @@ mod tests {
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opens_links_from_a_subfolder_beside_the_package() {
|
||||
let dir = std::env::temp_dir().join(format!("dc-idml-subfolder-links-{}", std::process::id()));
|
||||
let path = dir.join("images").join("logo.png");
|
||||
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||
// The author's absolute `/images/…` does not exist here; `images/` beside the .idml does.
|
||||
let (idml, png) = linked_idml("/images/logo.png", false).unwrap();
|
||||
std::fs::write(&path, &png).unwrap();
|
||||
|
||||
let doc = import(&idml, Some(&dir)).unwrap();
|
||||
let asset = doc.assets.values().next().unwrap();
|
||||
assert_eq!(*asset.data, png);
|
||||
assert_eq!(asset.link.as_deref(), std::path::absolute(&path).unwrap().to_str());
|
||||
assert_eq!(super::super::links::status(asset), "ok");
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remembers_flat_packaged_link_location() {
|
||||
let dir = std::env::temp_dir().join(format!("dc-idml-flat-links-{}", std::process::id()));
|
||||
|
||||
Reference in New Issue
Block a user