Skip to content

fix(csv-stringify): quote fields containing a bare CR or LF#493

Open
greymoth-jp wants to merge 1 commit into
adaltas:masterfrom
greymoth-jp:fix/csv-stringify-quote-cr-lf
Open

fix(csv-stringify): quote fields containing a bare CR or LF#493
greymoth-jp wants to merge 1 commit into
adaltas:masterfrom
greymoth-jp:fix/csv-stringify-quote-cr-lf

Conversation

@greymoth-jp

Copy link
Copy Markdown

Problem

stringify quotes a field only when it contains the quote, the delimiter, or the configured record_delimiter (default "\n"). A field that contains a bare carriage return is therefore emitted unquoted, but parse treats a lone CR as a record delimiter under its default auto-detection, so the output of stringify no longer round-trips through parse:

const { stringify } = require("csv-stringify/sync");
const { parse } = require("csv-parse/sync");

const csv = stringify([["x\ry", "z"]]); // "x\ry,z\n", field not quoted
parse(csv); // throws CSV_RECORD_INCONSISTENT_FIELDS_LENGTH

A \n round-trips because it matches the default record_delimiter, and a \r\n round-trips because its \n matches, but a bare \r slips past every check. The same gap applies to a \n inside a field when a non-\n record_delimiter is configured.

Fix

Quote a field when it contains a CR or LF. parse recognizes CR, LF and CRLF as record delimiters in its default auto-detection mode regardless of the delimiter used to write the record, so a field carrying either must be quoted to round-trip. This matches RFC 4180 section 2.6 (fields with line breaks must be enclosed in double quotes) and the behavior of other CSV writers.

Quoting is sufficient, since a quoted field with a CR already round-trips:

parse('"x\ry",z\n'); // [["x\ry", "z"]]

Test

Added a case under Option record_delimiter asserting a field with a bare CR is quoted. Reverting the fix makes only that case fail (expected 'x\ry,z' to equal '"x\ry",z'); the rest of the csv-stringify suite stays green.

A field holding a carriage return or line feed is left unquoted unless it
contains the configured record_delimiter (default "\n"), so a lone "\r"
fails to round-trip: parse auto-detects CR as a record delimiter and reports
CSV_RECORD_INCONSISTENT_FIELDS_LENGTH. Quote any field that contains CR or LF.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant