From 44fd4aec60010932c40b0c75a450e88f8b8f8da4 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 13 Nov 2026 01:42:41 -0500 Subject: [PATCH] Route CLI format dispatch through shared registry --- Cargo.lock | 2 ++ apps/designcraft-cli/Cargo.toml | 1 + apps/designcraft-cli/src/main.rs | 6 +++--- crates/engine/src/cmd/book.rs | 2 +- crates/mcp/Cargo.toml | 1 + crates/mcp/src/headless.rs | 4 ++-- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92227fc93..891437aa0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1675,6 +1675,7 @@ dependencies = [ name = "designcraft-cli" version = "0.20.1" dependencies = [ + "craft-file-formats", "designcraft-color", "designcraft-compose", "designcraft-doc", @@ -1863,6 +1864,7 @@ dependencies = [ name = "designcraft-mcp" version = "0.20.1" dependencies = [ + "craft-file-formats", "designcraft-engine", "designcraft-geom", "designcraft-render", diff --git a/apps/designcraft-cli/Cargo.toml b/apps/designcraft-cli/Cargo.toml index ab2464147..edebc5e29 100644 --- a/apps/designcraft-cli/Cargo.toml +++ b/apps/designcraft-cli/Cargo.toml @@ -22,5 +22,6 @@ designcraft-compose = { workspace = true } designcraft-format = { workspace = true } designcraft-pdf = { workspace = true } designcraft-mcp = { workspace = true } +craft-file-formats = { workspace = true } image = { workspace = true } serde_json = { workspace = true } diff --git a/apps/designcraft-cli/src/main.rs b/apps/designcraft-cli/src/main.rs index 79997e0ae..23817bbe7 100644 --- a/apps/designcraft-cli/src/main.rs +++ b/apps/designcraft-cli/src/main.rs @@ -597,8 +597,8 @@ fn export(s: &mut Session, out: &str, page: usize, scale: f64) -> Result<(), Str let img = r .render_page(&st.doc, &s.cache, page, scale, true, &designcraft_render::RenderOptions { printing_only: true, ..Default::default() }) .ok_or("no such page")?; - let lower = out.to_lowercase(); - let bytes = if lower.ends_with(".jpg") || lower.ends_with(".jpeg") { img.to_jpeg(90) } else { img.to_png() }; + let jpeg = craft_file_formats::detect(out, &[]) == Some(craft_file_formats::Format::Jpeg); + let bytes = if jpeg { img.to_jpeg(90) } else { img.to_png() }; designcraft_engine::atomic::write_atomic(std::path::Path::new(out), &bytes).map_err(|e| format!("{out}: {e}"))?; eprintln!("wrote {out} ({}×{}, {:.1} ms, {} glyphs)", img.width, img.height, t.elapsed().as_secs_f64() * 1000.0, r.stats.glyphs); Ok(()) @@ -645,7 +645,7 @@ fn script(args: &[String]) -> Result<(), String> { match a.as_str() { "--in" => { let p = val()?; - let cmd = if p.to_lowercase().ends_with(".idml") { "file.openIdml" } else { "file.open" }; + let cmd = if craft_file_formats::detect(&p, &[]) == Some(craft_file_formats::Format::Idml) { "file.openIdml" } else { "file.open" }; setup.push((cmd.into(), json!({"path": p}))); } "--sample" => setup.push(("file.newSample".into(), json!({}))), diff --git a/crates/engine/src/cmd/book.rs b/crates/engine/src/cmd/book.rs index b1de3dac7..2b171d388 100644 --- a/crates/engine/src/cmd/book.rs +++ b/crates/engine/src/cmd/book.rs @@ -130,7 +130,7 @@ impl ChapterBatch { fn writable_chapter(s: &Session, path: &str, command: &'static str) -> Result<()> { use std::path::Path; - if Path::new(path).extension().and_then(std::ffi::OsStr::to_str).is_some_and(|ext| ext.eq_ignore_ascii_case("idml")) { + if Path::new(path).extension().and_then(std::ffi::OsStr::to_str).is_some_and(|ext| craft_file_formats::from_extension(ext) == Some(craft_file_formats::Format::Idml)) { return Err(bad(command, format!("cannot change imported IDML chapter {path}; convert it to a native DesignCraft document first"))); } let target = crate::io::canonicalize(path).map_err(|e| EngineError::Other(format!("{path}: {e}")))?; diff --git a/crates/mcp/Cargo.toml b/crates/mcp/Cargo.toml index fa863aa94..da6434f82 100644 --- a/crates/mcp/Cargo.toml +++ b/crates/mcp/Cargo.toml @@ -12,6 +12,7 @@ workspace = true designcraft-engine = { workspace = true } designcraft-render = { workspace = true } designcraft-tools = { workspace = true } +craft-file-formats = { workspace = true } designcraft-geom = { workspace = true } serde_json = { workspace = true } log = { workspace = true } diff --git a/crates/mcp/src/headless.rs b/crates/mcp/src/headless.rs index a81aba154..8023e41da 100644 --- a/crates/mcp/src/headless.rs +++ b/crates/mcp/src/headless.rs @@ -259,8 +259,8 @@ impl Headless { .renderer .render_page(&st.doc, &self.session.cache, page, scale, false, &RenderOptions { printing_only: true, ..Default::default() }) .ok_or_else(|| format!("no page {page}"))?; - let lower = path.to_ascii_lowercase(); - let bytes = if lower.ends_with(".jpg") || lower.ends_with(".jpeg") { img.to_jpeg(90) } else { img.to_png() }; + let jpeg = craft_file_formats::detect(path, &[]) == Some(craft_file_formats::Format::Jpeg); + let bytes = if jpeg { img.to_jpeg(90) } else { img.to_png() }; designcraft_engine::io::write_file(path, &bytes)?; Ok(json!({"path": path, "width": img.width, "height": img.height})) }