From c6bb7a2f57c8a035b9a3c507891d50f4e64a0c37 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Nov 2026 09:12:52 +0000 Subject: [PATCH] Fields: a date-time picture's quoted text is shown as it is MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Word's date-time pictures (`DATE \@ "…"`) put literal text in single quotes, two quotes in a row standing for one: `H' o''clock'` shows "8 o'clock". The formatter read the quotes as text and the letters inside as instructions (an `a` became AM or PM). Quoted text is now shown as it is; an unclosed quote runs to the end. Regression test: `date_pictures_keep_quoted_text`. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01GBVQLyDnrG8Tn1yDQcUabC --- crates/engine/src/cmd/insert/items.rs | 16 ++++++++++++++++ crates/engine/src/cmd/insert/tests.rs | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/crates/engine/src/cmd/insert/items.rs b/crates/engine/src/cmd/insert/items.rs index 78e08b5fb7..d421a4f736 100644 --- a/crates/engine/src/cmd/insert/items.rs +++ b/crates/engine/src/cmd/insert/items.rs @@ -83,6 +83,22 @@ pub fn format_date_parts(fmt: &str, y: i64, m: usize, d: u32, (hh, mm, ss): (u32 let mut i = 0; while i < chars.len() { let c = chars.get(i).copied().unwrap_or(' '); + // Text in single quotes is shown as it is; two quotes in a row are one. + if c == '\'' { + i += 1; + while let Some(&q) = chars.get(i) { + i += 1; + if q != '\'' { + out.push(q); + } else if chars.get(i) == Some(&'\'') { + out.push('\''); + i += 1; + } else { + break; + } + } + continue; + } // `am/pm` (any case) is one token: AM or PM. if chars.get(i..i + 5).is_some_and(|w| w.iter().collect::().eq_ignore_ascii_case("am/pm")) { out.push_str(if hh < 12 { "AM" } else { "PM" }); diff --git a/crates/engine/src/cmd/insert/tests.rs b/crates/engine/src/cmd/insert/tests.rs index fbff175e70..eaa844edae 100644 --- a/crates/engine/src/cmd/insert/tests.rs +++ b/crates/engine/src/cmd/insert/tests.rs @@ -334,6 +334,15 @@ fn symbol_takes_its_own_font() { assert!(s.run("insert.symbol", &json!({"char": ""})).is_err()); } +#[test] +fn date_pictures_keep_quoted_text() { + // Text in single quotes is shown as it is (Word's date-time picture); two quotes are one. + assert_eq!(format_date_parts("H' o''clock'", 2026, 10, 21, (8, 0, 0), 0), "8 o'clock"); + assert_eq!(format_date_parts("'Day' d 'at' h", 2026, 10, 21, (17, 0, 0), 0), "Day 21 at 5"); + // An unclosed quote runs to the end. + assert_eq!(format_date_parts("yyyy 'and so", 2026, 10, 21, (0, 0, 0), 0), "2026 and so"); +} + #[test] fn date_pictures() { // Word accepts either case for the day and year instructions.