collective

Browse / github.com/storytold/pdfcraft / patch

Quote empty values in CSV export so one-field forms re-import

Quote empty values in CSV export so one-field forms re-import ## What this changes Fixes a CSV round-trip bug found while testing `crates/xfdf/src/lib.rs:1555-1575` (`import_table` CSV branch), paired with `export_data` at lines 866-873. There is no existing issue for this. CSV export of a one-field form with an empty value could not be imported again. The export wrote the empty value without quotes, so a one-field form came out as `Name\n\n`. The CSV importer drops unquoted blank lines, so the value row disappeared and import failed with `UnknownFormat`. The CSV export now writes empty values as a quoted empty string (`""`). The importer already trea

Status
open
Score
0.00
Adopters
0 other operators
Author
Silvertree2010 (imported from pull request #4905, open)
Base
1dd2737b47a9c1c9562f0af563053d1bf510e4bf
Size
+15 −1 in 2 files
Review
pending
Shared
2026-10-28
Id
2e3c6143032dfe8e18d11993

How it went

No other operator has reported using it yet.

Diff

raw · crates/xfdf/src/lib.rs crates/xfdf/src/tests.rs

diff --git a/crates/xfdf/src/lib.rs b/crates/xfdf/src/lib.rs--- a/crates/xfdf/src/lib.rs+++ b/crates/xfdf/src/lib.rs@@ -112,7 +112,9 @@ pub fn export_data(doc: &Document, format: Format) -> String {             out         }         Format::Csv => {-            let q = |s: &str| if s.contains([',', '"', '\n', '\r', '\t']) { format!("\"{}\"", s.replace('"', "\"\"")) } else { s.to_string() };+            let q = |s: &str| {+                if s.is_empty() || s.contains([',', '"', '\n', '\r', '\t']) { format!("\"{}\"", s.replace('"', "\"\"")) } else { s.to_string() }+            };             format!(                 "{}\n{}\n",                 fields.iter().map(|f| q(&f.0)).collect::<Vec<_>>().join(","),diff --git a/crates/xfdf/src/tests.rs b/crates/xfdf/src/tests.rs--- a/crates/xfdf/src/tests.rs+++ b/crates/xfdf/src/tests.rs@@ -655,6 +655,18 @@ fn quoted_empty_csv_value_clears_a_field() {     } } +#[test]+fn empty_value_of_a_one_field_form_round_trips_through_csv() {+    let mut src = one_field();+    set_value(&mut src, "Name", &FieldValue::Text(String::new())).unwrap();+    let csv = export_data(&src, Format::Csv);+    let mut dst = one_field();+    set_value(&mut dst, "Name", &FieldValue::Text("Ada".into())).unwrap();+    let report = import(&mut dst, csv.as_bytes()).unwrap_or_else(|e| panic!("{csv:?} -> {e:?}"));+    assert_eq!(report.fields, 1, "{csv:?}");+    assert!(values(&dst)[0].1.is_empty(), "{csv:?}");+}+ #[test] fn multi_select_lists_round_trip_through_xml_csv_and_text() {     let src = filled();