Merge pull request #2125 from Tom-R-Main/openbytes-title

File import: keep native and IDML bytes out of the INDD converter
This commit is contained in:
Brandon Thomas authored and GitHub committed 2026-11-02 23:24:12 -05:00
commit 1e2d75d0b0
4 files changed
+41 -6

No files matched your search

+1 -1
View File
@@ -393,7 +393,7 @@ Newest first.
- **2026-11-03** · `type.char` says when the font it applies isn't available (#2189): it returns `{"warnings": ["Missing font: Courier Prime (using Source Sans 3)"]}`, or `Missing font style: …` for a style the family doesn't have, in preflight's words. The font is still applied, as before, so Find Font and preflight list it. A script that asked for a font the machine doesn't have exported in the substitute with no word about it. No readiness percentage change.
- **2026-11-01** · Parent page resizing (#1620): Properties, the Page Tool Control panel and on-page handles resize the selected parent page independently of document pages. Stable parent IDs, repeated resizing, anchors and liquid rules are preserved on the current command modules. Inline parent margin editing targets only the selected parent page and preserves opposite-page margins and document overrides; document commands retain their first-page default before the canvas is initialized. No readiness percentage change.
- **2026-10-31** · `font.list` reports the embedding licence of the face that sets each font's text: its OS/2 `fsType` and what the bits mean (`restrictedLicence`, `bitmapOnly`, `noSubsetting`, `editable`, `previewPrint`; null when the font is missing or has no OS/2 table). A script or host that makes PDFs can check every face, bundled and installed ones included, without reading font files. Export behaviour is unchanged. No readiness percentage change.
- **2026-10-31** · A `.designcraft` file opened from bytes (`file.openBytes` with its file name, as a browser or host passes it) is titled without the extension, as an IDML file opened that way is. Saving it in the browser downloaded `Brochure.designcraft.designcraft`, and the File Name variable showed the doubled name. Browser Open and Drop pass the full file name, so only the engine removes the extension and a repeated suffix is kept in the title. No readiness percentage change.
- **2026-10-31** · A `.designcraft` file opened from bytes (`file.openBytes` with its file name, as a browser or host passes it) is titled without the extension, as an IDML file opened that way is. Saving it in the browser downloaded `Brochure.designcraft.designcraft`, and the File Name variable showed the doubled name. Browser Open and Drop pass the full file name, so only the engine removes the extension and a repeated suffix is kept in the title. Native and IDML content takes priority over a misleading `.indd` or `.indt` extension. No readiness percentage change.
- **2026-10-30** · Import warnings about a story have a Show button: it closes the warnings (the status line keeps them) and selects the story's first frame, fitted in the window. `file.open` returns `warningItems`, the frame each IDML or InDesign warning is about (or null), matching the converter's INDD story numbers (`story 30892`, written to IDML as `u78ac`) and IDML `Self` names to the imported stories. No readiness percentage change.
- **2026-10-30** · Parent pages: a running-header variable shows its name in angle brackets on the parent itself (it was blank), as InDesign shows it; on the document pages, and in text with no page, it shows its text as before. No readiness percentage change.
- **2026-10-30** · Without facing pages, a page of a multi-page spread shows the parent page in its place, as in InDesign: the second page of a two-page spread shows the parent's second page. Every single-sided page showed the parent's first page, so an InDesign book set up without facing pages but laid out in two-page spreads repeated the left parent page's items (a black heading bar) on its right pages and lost the right parent page's. No readiness percentage change.
+25
View File
@@ -420,6 +420,29 @@ mod open_bytes_tests {
use crate::Session;
#[test]
fn legacy_and_idml_bytes_named_as_indesign_files_open_without_conversion() {
let mut maker = Session::new();
maker.execute("file.new", &json!({})).unwrap();
let idml = designcraft_idml::export_idml(&maker.doc().unwrap().doc);
let base64 = super::super::bytes::base64_encode(&idml);
let legacy = super::super::bytes::base64_encode(&serde_json::to_vec(&maker.doc().unwrap().doc).unwrap());
for name in ["Brochure.indd", "Brochure.INDT"] {
let mut s = Session::new();
s.execute("file.openBytes", &json!({"name": name, "base64": legacy})).unwrap();
assert_eq!(s.documents().len(), 1, "legacy: {name}");
assert_eq!(s.doc().unwrap().doc.title, name, "legacy: {name}");
}
for command in ["file.openBytes", "file.openIdml"] {
for name in ["Brochure.indd", "Brochure.INDT"] {
let mut s = Session::new();
s.execute(command, &json!({"name": name, "base64": base64})).unwrap();
assert_eq!(s.documents().len(), 1, "{command}: {name}");
assert_eq!(s.doc().unwrap().doc.title, "Brochure", "{command}: {name}");
}
}
}
/// A `.designcraft` file opened from bytes under its file name (a browser or host passes the
/// name it has) is titled without the extension, as an IDML file is, so saving it gives
/// `Brochure.designcraft` and not `Brochure.designcraft.designcraft`.
@@ -433,6 +456,8 @@ mod open_bytes_tests {
("Brochure.DesignCraft", "Brochure"),
("Brochure", "Brochure"),
("Brochure.v2", "Brochure.v2"),
("Brochure.indd", "Brochure.indd"),
("Brochure.INDT", "Brochure.INDT"),
("Brochure.designcraft.designcraft", "Brochure.designcraft"),
(".designcraft", ".designcraft"),
// Names that aren't ASCII: cutting the extension's length off the end of the last one
+4 -2
View File
@@ -455,9 +455,11 @@ fn warning_item(
}
/// An InDesign document or template (.indd, .indt): known by its signature, or by its name when
/// the bytes are something else (the converter then says why it can't read them).
/// the bytes are neither a recognized DesignCraft document nor IDML. The converter explains
/// unrecognized data with an InDesign extension.
pub(crate) fn is_indd(name: &str, bytes: &[u8]) -> bool {
bytes.starts_with(&indd::header::SIGNATURE) || has_indd_extension(name)
bytes.starts_with(&indd::header::SIGNATURE)
|| (has_indd_extension(name) && !super::file::is_document(bytes) && !bytes.trim_ascii_start().starts_with(b"{"))
}
pub(crate) fn has_indd_extension(name: &str) -> bool {
+11 -3
View File
@@ -435,20 +435,28 @@ pub(crate) mod browser_import_tests {
("Brochure.designcraft", "Brochure"),
("Brochure.designcraft.designcraft", "Brochure.designcraft"),
("Brochure.v2.designcraft", "Brochure.v2"),
("Brochure.indd", "Brochure.indd"),
("Brochure.INDT", "Brochure.INDT"),
("日本.DESIGNCRAFT", "日本"),
(".designcraft", ".designcraft"),
("Brochure", "Brochure"),
] {
let before = app.session.documents().len();
let request = app.import_request(purpose);
deliver(&mut app, request, name, native.clone());
assert_eq!(app.session.documents().len(), before + 1, "{purpose}: {name}");
assert_eq!(app.session.doc().unwrap().doc.title, title, "{purpose}: {name}");
}
}
let idml = designcraft_idml::export_idml(&app.session.doc().unwrap().doc);
for purpose in ["open", "drop"] {
let request = app.import_request(purpose);
deliver(&mut app, request, "Brochure.idml", idml.clone());
assert_eq!(app.session.doc().unwrap().doc.title, "Brochure", "{purpose}: IDML");
for name in ["Brochure.idml", "Brochure.indd", "Brochure.INDT"] {
let before = app.session.documents().len();
let request = app.import_request(purpose);
deliver(&mut app, request, name, idml.clone());
assert_eq!(app.session.documents().len(), before + 1, "{purpose}: {name}");
assert_eq!(app.session.doc().unwrap().doc.title, "Brochure", "{purpose}: {name}");
}
}
}
fn image() -> Vec<u8> {