diff --git a/lib/__specs__/main.spec.ts b/lib/__specs__/main.spec.ts index 7b39a9d..32e8dae 100644 --- a/lib/__specs__/main.spec.ts +++ b/lib/__specs__/main.spec.ts @@ -196,6 +196,44 @@ describe("ExportToCsv", () => { ); }); + it("should escape double quotes when quote is double quote", () => { + const options: ConfigOptions = { + quoteCharacter: '"', + filename: "Test Csv 2", + useBom: false, + showColumnHeaders: true, + useKeysAsHeaders: true, + }; + + const output = generateCsv(options)([ + { + "escape-it": 24, + song: 'Mack "The Knife"', + }, + ]); + + expect(output).toBe('"escape-it","song"\r\n24,"Mack ""The Knife"""\r\n'); + }); + + it("should not escape double quotes when quote is not double quote", () => { + const options: ConfigOptions = { + quoteCharacter: "'", + filename: "Test Csv 2", + useBom: false, + showColumnHeaders: true, + useKeysAsHeaders: true, + }; + + const output = generateCsv(options)([ + { + "escape-it": 24, + song: 'Mack "The Knife"', + }, + ]); + + expect(output).toBe("'escape-it','song'\r\n24,'Mack \"The Knife\"'\r\n"); + }); + it("should properly quote headers", () => { const options: ConfigOptions = { filename: "Test Csv 2", diff --git a/lib/helpers.ts b/lib/helpers.ts index 21afb45..658ba58 100644 --- a/lib/helpers.ts +++ b/lib/helpers.ts @@ -133,10 +133,14 @@ export const formatData = (config: ConfigOptions, data: any): string => { if ( config.quoteStrings || (config.fieldSeparator && data.indexOf(config.fieldSeparator) > -1) || + (config.quoteCharacter && data.indexOf(config.quoteCharacter) > -1) || data.indexOf("\n") > -1 || data.indexOf("\r") > -1 ) { - val = config.quoteCharacter + data + config.quoteCharacter; + val = + config.quoteCharacter + + escapeDoubleQuotes(data, config.quoteCharacter) + + config.quoteCharacter; } return val; } @@ -149,3 +153,17 @@ export const formatData = (config: ConfigOptions, data: any): string => { } return data; }; + +/** + * If double-quotes are used to enclose fields, then a double-quote + * appearing inside a field must be escaped by preceding it with + * another double quote. + * + * See https://www.rfc-editor.org/rfc/rfc4180 + */ +function escapeDoubleQuotes(data: string, quoteCharacter?: string): string { + if (quoteCharacter == '"' && data.indexOf('"') > -1) { + return data.replace(/"/g, '""'); + } + return data; +}