From d8b56e12c766279ff24d5cf90e5604df6f3d4e27 Mon Sep 17 00:00:00 2001 From: asssslay Date: Tue, 3 Nov 2026 22:46:49 +0300 Subject: [PATCH 1/2] fix(csv-stringify): preserve field contents when quoting is disabled --- packages/csv-stringify/lib/api/index.js | 2 +- packages/csv-stringify/test/option.quote.ts | 53 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/csv-stringify/lib/api/index.js b/packages/csv-stringify/lib/api/index.js index 1fb77be2b..b3f40e5d4 100644 --- a/packages/csv-stringify/lib/api/index.js +++ b/packages/csv-stringify/lib/api/index.js @@ -256,7 +256,7 @@ const stringifier = function (options, state, info) { quoted || quotedString || quotedMatch; - if (shouldQuote === true && containsEscape === true) { + if (shouldQuote === true && containsEscape === true && quote !== "") { value = value.replaceAll(escape, () => escape + escape); } if (containsQuote === true) { diff --git a/packages/csv-stringify/test/option.quote.ts b/packages/csv-stringify/test/option.quote.ts index 66d1902fa..164ed27bf 100644 --- a/packages/csv-stringify/test/option.quote.ts +++ b/packages/csv-stringify/test/option.quote.ts @@ -4,6 +4,59 @@ import { stringify } from "../lib/index.js"; import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `quote`", function () { + it("preserves special characters when quoting is disabled", function () { + for (const quote of [false, ""]) { + stringifySync([['say "hi", bob'], ['say "hi"\nbob']], { + quote, + }).should.eql('say "hi", bob\nsay "hi"\nbob\n'); + } + }); + + it("preserves fields selected for quoting when quoting is disabled", function () { + for (const quote of [false, ""]) { + for (const options of [ + { quoted: true }, + { quoted_string: true }, + { quoted_match: /hi/ }, + ]) { + stringifySync([['say "hi"']], { quote, ...options }).should.eql( + 'say "hi"\n', + ); + } + } + }); + + it("preserves quotes supplied by a cast with quoting disabled", function () { + stringifySync([["abc", 1]], { + quoted: true, + cast: { + number: (value) => ({ value: `="${value}"`, quote: false }), + }, + }).should.eql('"abc",="1"\n'); + }); + + it("preserves custom escape characters when quoting is disabled", function () { + stringifySync([["C:\\dir,x"]], { + quote: false, + escape: "\\", + }).should.eql("C:\\dir,x\n"); + }); + + it("preserves quotes in fields containing a custom delimiter", function () { + stringifySync([['{"a":1}\tx']], { + quote: "", + delimiter: "\t", + }).should.eql('{"a":1}\tx\n'); + }); + + it("preserves selected fields in the callback API with quoting disabled", function (next) { + stringify([['say "hi"']], { quote: false, quoted: true }, (err, data) => { + if (err) return next(err); + data.should.eql('say "hi"\n'); + next(); + }); + }); + it("default", function (next) { const stringifier = stringify([], () => { stringifier.options.quote.should.eql('"'); From 3a42778d63a6d79d3ec8f9f14ad67d99b6ffa335 Mon Sep 17 00:00:00 2001 From: David Worms Date: Tue, 3 Nov 2026 22:47:37 +0100 Subject: [PATCH 2/2] test(csv-parse): minor test improvements --- packages/csv-stringify/test/option.quote.ts | 104 ++++++++++---------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/packages/csv-stringify/test/option.quote.ts b/packages/csv-stringify/test/option.quote.ts index 164ed27bf..9464a2857 100644 --- a/packages/csv-stringify/test/option.quote.ts +++ b/packages/csv-stringify/test/option.quote.ts @@ -4,59 +4,6 @@ import { stringify } from "../lib/index.js"; import { stringify as stringifySync } from "../lib/sync.js"; describe("Option `quote`", function () { - it("preserves special characters when quoting is disabled", function () { - for (const quote of [false, ""]) { - stringifySync([['say "hi", bob'], ['say "hi"\nbob']], { - quote, - }).should.eql('say "hi", bob\nsay "hi"\nbob\n'); - } - }); - - it("preserves fields selected for quoting when quoting is disabled", function () { - for (const quote of [false, ""]) { - for (const options of [ - { quoted: true }, - { quoted_string: true }, - { quoted_match: /hi/ }, - ]) { - stringifySync([['say "hi"']], { quote, ...options }).should.eql( - 'say "hi"\n', - ); - } - } - }); - - it("preserves quotes supplied by a cast with quoting disabled", function () { - stringifySync([["abc", 1]], { - quoted: true, - cast: { - number: (value) => ({ value: `="${value}"`, quote: false }), - }, - }).should.eql('"abc",="1"\n'); - }); - - it("preserves custom escape characters when quoting is disabled", function () { - stringifySync([["C:\\dir,x"]], { - quote: false, - escape: "\\", - }).should.eql("C:\\dir,x\n"); - }); - - it("preserves quotes in fields containing a custom delimiter", function () { - stringifySync([['{"a":1}\tx']], { - quote: "", - delimiter: "\t", - }).should.eql('{"a":1}\tx\n'); - }); - - it("preserves selected fields in the callback API with quoting disabled", function (next) { - stringify([['say "hi"']], { quote: false, quoted: true }, (err, data) => { - if (err) return next(err); - data.should.eql('say "hi"\n'); - next(); - }); - }); - it("default", function (next) { const stringifier = stringify([], () => { stringifier.options.quote.should.eql('"'); @@ -294,4 +241,55 @@ describe("Option `quote`", function () { eof: false, }).should.eql("|a\\|b|"); }); + + describe("disabled", function () { + it("preserves special characters when quoting is disabled", function () { + stringifySync([['say "hi", bob'], ['say "hi"\nbob']], { + quote: false, + }).should.eql('say "hi", bob\nsay "hi"\nbob\n'); + }); + + it("preserves fields selected for quoting when quoting is disabled", function () { + for (const options of [ + { quoted: true }, + { quoted_string: true }, + { quoted_match: /hi/ }, + ]) { + stringifySync([['say "hi"']], { quote: false, ...options }).should.eql( + 'say "hi"\n', + ); + } + }); + + it("preserves quotes supplied by a cast with quoting disabled", function () { + stringifySync([["abc", 1]], { + quoted: true, + cast: { + number: (value) => ({ value: `="${value}"`, quote: false }), + }, + }).should.eql('"abc",="1"\n'); + }); + + it("preserves custom escape characters when quoting is disabled", function () { + stringifySync([["C:\\dir,x"]], { + quote: false, + escape: "\\", + }).should.eql("C:\\dir,x\n"); + }); + + it("preserves quotes in fields containing a custom delimiter", function () { + stringifySync([['{"a":1}\tx']], { + quote: "", + delimiter: "\t", + }).should.eql('{"a":1}\tx\n'); + }); + + it("preserves selected fields in the callback API with quoting disabled", function (next) { + stringify([['say "hi"']], { quote: false, quoted: true }, (err, data) => { + if (err) return next(err); + data.should.eql('say "hi"\n'); + next(); + }); + }); + }); });