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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant