From 2ee8ce1ac1e6a76319bb5dcffafd1d4c5879a55f Mon Sep 17 00:00:00 2001 From: Marco Arnulfo <103679419+marcoarnulfo@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:53:10 +0200 Subject: [PATCH] fix(forms): keep a whitespace-only value in a text field without a format (#1323) (#1403) The commit-time Keystroke check returned an empty value for any whitespace-only text before looking at the field's format, so setting a space, a tab or a non-breaking space in a plain text field reported success and removed the field's value. Text and XFDF imports go through the same setter and lost the value the same way. Blank input now clears only a field with a format (number, percent, date, time, special or mask), as before; a field without one stores the text as given. An empty value still clears any field. Adds tests::whitespace_only_text_is_kept_in_a_field_without_a_format and a keystroke assertion in af::tests::numbers_format_like_acrobat, both of which fail before this change. --- crates/forms/src/af.rs | 6 +++++- crates/forms/src/tests.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/forms/src/af.rs b/crates/forms/src/af.rs index 37ee30ca..be38a954 100644 --- a/crates/forms/src/af.rs +++ b/crates/forms/src/af.rs @@ -823,7 +823,8 @@ pub fn format_value(f: &Format, value: &str) -> String { /// (numbers are normalised), or Acrobat's message. pub fn keystroke(f: &Format, field: &str, value: &str) -> Result { let bad = || format!("The value entered does not match the format of the field [ {field} ]"); - if value.trim().is_empty() { + // Blank input clears a formatted field; without a format, whitespace is text like any other. + if *f != Format::None && value.trim().is_empty() { return Ok(String::new()); } match f { @@ -1045,6 +1046,9 @@ mod tests { keystroke(&n(2, 0, 0, "$", true), "Total", "ten"), Err("The value entered does not match the format of the field [ Total ]".into()) ); + // Blank input clears a formatted field (#1323); without a format it is text like any other. + assert_eq!(keystroke(&n(2, 0, 0, "$", true), "Total", " \t"), Ok(String::new())); + assert_eq!(keystroke(&Format::None, "Name", " \t"), Ok(" \t".into())); } #[test] diff --git a/crates/forms/src/tests.rs b/crates/forms/src/tests.rs index bee36653..5410d767 100644 --- a/crates/forms/src/tests.rs +++ b/crates/forms/src/tests.rs @@ -232,6 +232,21 @@ fn opt_export_values_select_button_states() { assert!(err.to_string().contains("options: Post, Pick-up"), "{err}"); } +/// Issue #1323: a text field without a format keeps a whitespace-only value as typed; only an +/// empty value clears it. +#[test] +fn whitespace_only_text_is_kept_in_a_field_without_a_format() { + for value in [" ", "\t", "\u{a0}"] { + let mut doc = fixture(); + set_value(&mut doc, "name", &FieldValue::Text(value.into())).unwrap(); + let doc = reopen(&doc); + assert_eq!(field(&fields(&doc), "name").value, [value], "{value:?}"); + } + let mut doc = fixture(); + set_value(&mut doc, "name", &FieldValue::Text(String::new())).unwrap(); + assert!(field(&fields(&reopen(&doc)), "name").value.is_empty()); +} + #[test] fn text_fields_get_new_appearances() { let mut doc = fixture();