From 7d5720864fcbc59d41118a926831bee5dddd4651 Mon Sep 17 00:00:00 2001 From: Juanjo Diaz Date: Wed, 23 May 2018 23:18:35 +0300 Subject: [PATCH] fix: Escape custom quotes correctly (#301) --- lib/JSON2CSVBase.js | 24 ++++++++++++++++------ test/CLI.js | 11 ++++++++++ test/JSON2CSVParser.js | 13 ++++++++++++ test/JSON2CSVTransform.js | 19 +++++++++++++++++ test/fixtures/csv/escapeCustomQuotes.json | 2 ++ test/fixtures/json/escapeCustomQuotes.json | 3 +++ 6 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/csv/escapeCustomQuotes.json create mode 100644 test/fixtures/json/escapeCustomQuotes.json diff --git a/lib/JSON2CSVBase.js b/lib/JSON2CSVBase.js index 80ca4409..dd3d5b21 100644 --- a/lib/JSON2CSVBase.js +++ b/lib/JSON2CSVBase.js @@ -178,12 +178,24 @@ class JSON2CSVBase { .replace(/\u2029/g, '\r'); } - //Replace single quote with double quote. Single quote are preceeded by - //a backslash, and it's not at the end of the stringifiedValue. - stringifiedValue = stringifiedValue - .replace(/^"(.*)"$/, this.opts.quote + '$1' + this.opts.quote) - .replace(/(\\")(?!$)/g, this.opts.doubleQuote) - .replace(/\\\\/g, '\\'); + + if (this.opts.quote === '"') { + // Replace automatically scaped single quotes by doubleQuotes + stringifiedValue = stringifiedValue + .replace(/(\\")(?!$)/g, this.opts.doubleQuote); + } else { + // Unescape automatically escaped double quote symbol + // Replace wrapping quotes + // Replace single quote with double quote + stringifiedValue = stringifiedValue + .replace(/(\\")(?!$)/g, '"') + .replace(new RegExp(this.opts.quote, 'g'), this.opts.doubleQuote) + .replace(/^"(.*)"$/, this.opts.quote + '$1' + this.opts.quote); + } + + // Remove double backslashes + stringifiedValue = stringifiedValue + .replace(/\\\\/g, '\\'); if (this.opts.excelStrings && typeof value === 'string') { stringifiedValue = '"="' + stringifiedValue + '""'; diff --git a/test/CLI.js b/test/CLI.js index 02f483d4..100a5f4e 100644 --- a/test/CLI.js +++ b/test/CLI.js @@ -396,6 +396,17 @@ module.exports = (testRunner, jsonFixtures, csvFixtures) => { }); }); + testRunner.add('should escape quotes when setting \'quote\' property is present', (t) => { + const opts = ' --fields carModel,color --quote "\'"'; + + child_process.exec(cli + '-i ' + getFixturePath('/json/escapeCustomQuotes.json') + opts, (err, stdout, stderr) => { + t.notOk(stderr); + const csv = stdout; + t.equal(csv, csvFixtures.escapeCustomQuotes); + t.end(); + }); + }); + // Double Quote testRunner.add('should escape quotes with double quotes', (t) => { diff --git a/test/JSON2CSVParser.js b/test/JSON2CSVParser.js index ca55b184..72429553 100644 --- a/test/JSON2CSVParser.js +++ b/test/JSON2CSVParser.js @@ -413,6 +413,19 @@ module.exports = (testRunner, jsonFixtures, csvFixtures) => { t.end(); }); + testRunner.add('should escape quotes when setting \'quote\' property is present', (t) => { + const opts = { + fields: ['carModel', 'color'], + quote: '\'' + }; + + const parser = new Json2csvParser(opts); + const csv = parser.parse(jsonFixtures.escapeCustomQuotes); + + t.equal(csv, csvFixtures.escapeCustomQuotes); + t.end(); + }); + // Double Quote testRunner.add('should escape quotes with double quotes', (t) => { diff --git a/test/JSON2CSVTransform.js b/test/JSON2CSVTransform.js index 59de2b2f..03b50c59 100644 --- a/test/JSON2CSVTransform.js +++ b/test/JSON2CSVTransform.js @@ -589,6 +589,25 @@ module.exports = (testRunner, jsonFixtures, csvFixtures) => { .on('error', err => t.notOk(true, err.message)); }); + testRunner.add('should escape quotes when setting \'quote\' property is present', (t) => { + const opts = { + fields: ['carModel', 'color'], + quote: '\'' + }; + + const transform = new Json2csvTransform(opts); + const processor = jsonFixtures.escapeCustomQuotes().pipe(transform); + + let csv = ''; + processor + .on('data', chunk => (csv += chunk.toString())) + .on('end', () => { + t.equal(csv, csvFixtures.escapeCustomQuotes); + t.end(); + }) + .on('error', err => t.notOk(true, err.message)); + }); + // Double Quote testRunner.add('should escape quotes with double quotes', (t) => { diff --git a/test/fixtures/csv/escapeCustomQuotes.json b/test/fixtures/csv/escapeCustomQuotes.json new file mode 100644 index 00000000..849b6251 --- /dev/null +++ b/test/fixtures/csv/escapeCustomQuotes.json @@ -0,0 +1,2 @@ +'carModel','color' +'''Audi''','''blue''' \ No newline at end of file diff --git a/test/fixtures/json/escapeCustomQuotes.json b/test/fixtures/json/escapeCustomQuotes.json new file mode 100644 index 00000000..91c56e6d --- /dev/null +++ b/test/fixtures/json/escapeCustomQuotes.json @@ -0,0 +1,3 @@ +[ + { "carModel": "'Audi'", "price": 0, "color": "'blue'" } +] \ No newline at end of file