From 286154a17cfc0dac1b2bbec4e4a89c251f923493 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 25 Oct 2026 17:16:44 +0000 Subject: [PATCH] Accept a UTF-8 BOM at the start of lightcraft-cli --script files Fixes #2937 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- apps/lightcraft-cli/src/main.rs | 4 ++++ apps/lightcraft-cli/tests/it/cli.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/apps/lightcraft-cli/src/main.rs b/apps/lightcraft-cli/src/main.rs index a27e97beb..b2d3804b3 100644 --- a/apps/lightcraft-cli/src/main.rs +++ b/apps/lightcraft-cli/src/main.rs @@ -557,6 +557,8 @@ fn run(args: &[String]) -> Result<(), String> { } else { std::fs::read_to_string(path).map_err(|e| format!("{path}: {e}"))? }; + // Windows PowerShell 5.1 writes a UTF-8 BOM; it is not part of the first JSON line. + let text = text.strip_prefix('\u{feff}').unwrap_or(&text); for (n, line) in text.lines().enumerate().filter(|(_, l)| !l.trim().is_empty() && !l.trim_start().starts_with('#')) { let v: Value = serde_json::from_str(line).map_err(|e| format!("{path}:{}: {e}", n + 1))?; // `{"command": id, "params": …}` or a control request `{"method": m, "params": …}` @@ -851,6 +853,8 @@ fn snapshot(args: &[String]) -> Result<(), String> { let mut failed = 0usize; if let Some(script) = &script { let text = std::fs::read_to_string(script).map_err(|e| format!("{script}: {e}"))?; + // Windows PowerShell 5.1 writes a UTF-8 BOM; it is not part of the first JSON line. + let text = text.strip_prefix('\u{feff}').unwrap_or(&text); let mut out = std::io::stdout().lock(); for (n, line) in text.lines().enumerate() { let line = line.trim(); diff --git a/apps/lightcraft-cli/tests/it/cli.rs b/apps/lightcraft-cli/tests/it/cli.rs index 1c8910d9d..04a74560c 100644 --- a/apps/lightcraft-cli/tests/it/cli.rs +++ b/apps/lightcraft-cli/tests/it/cli.rs @@ -506,6 +506,20 @@ fn run_cli(args: &[&str], stdin: Option<&str>) -> (bool, Vec, String) { (o.status.success(), lines, String::from_utf8_lossy(&o.stderr).to_string()) } +/// Windows PowerShell 5.1 writes a UTF-8 BOM; `--script` (file and stdin) must accept it. +#[test] +fn run_script_accepts_a_utf8_bom() { + let text = "\u{feff}{\"command\": \"library.info\", \"params\": {}}\n"; + let script = tmp("bom-steps.jsonl"); + std::fs::write(&script, text).unwrap(); + let (ok, lines, err) = run_cli(&["--demo", "--script", script.to_str().unwrap()], None); + assert!(ok, "file: {err}"); + assert_eq!(lines.len(), 1, "{lines:?}"); + let (ok, lines, err) = run_cli(&["--demo", "--script", "-"], Some(text)); + assert!(ok, "stdin: {err}"); + assert_eq!(lines.len(), 1, "{lines:?}"); +} + #[test] fn run_subcommand_chains_commands_and_persists_a_library() { let input = tmp("run-in.png");