Skip to content

Commit fd09d60

Browse files
authoredOct 27, 2023
Escape double quotes according to RFC 4180 (#66)
Fixes #65
1 parent 7f117d9 commit fd09d60

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed
 

‎lib/__specs__/main.spec.ts

+38
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,44 @@ describe("ExportToCsv", () => {
196196
);
197197
});
198198

199+
it("should escape double quotes when quote is double quote", () => {
200+
const options: ConfigOptions = {
201+
quoteCharacter: '"',
202+
filename: "Test Csv 2",
203+
useBom: false,
204+
showColumnHeaders: true,
205+
useKeysAsHeaders: true,
206+
};
207+
208+
const output = generateCsv(options)([
209+
{
210+
"escape-it": 24,
211+
song: 'Mack "The Knife"',
212+
},
213+
]);
214+
215+
expect(output).toBe('"escape-it","song"\r\n24,"Mack ""The Knife"""\r\n');
216+
});
217+
218+
it("should not escape double quotes when quote is not double quote", () => {
219+
const options: ConfigOptions = {
220+
quoteCharacter: "'",
221+
filename: "Test Csv 2",
222+
useBom: false,
223+
showColumnHeaders: true,
224+
useKeysAsHeaders: true,
225+
};
226+
227+
const output = generateCsv(options)([
228+
{
229+
"escape-it": 24,
230+
song: 'Mack "The Knife"',
231+
},
232+
]);
233+
234+
expect(output).toBe("'escape-it','song'\r\n24,'Mack \"The Knife\"'\r\n");
235+
});
236+
199237
it("should properly quote headers", () => {
200238
const options: ConfigOptions = {
201239
filename: "Test Csv 2",

‎lib/helpers.ts

+19-1
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,14 @@ export const formatData = (config: ConfigOptions, data: any): string => {
133133
if (
134134
config.quoteStrings ||
135135
(config.fieldSeparator && data.indexOf(config.fieldSeparator) > -1) ||
136+
(config.quoteCharacter && data.indexOf(config.quoteCharacter) > -1) ||
136137
data.indexOf("\n") > -1 ||
137138
data.indexOf("\r") > -1
138139
) {
139-
val = config.quoteCharacter + data + config.quoteCharacter;
140+
val =
141+
config.quoteCharacter +
142+
escapeDoubleQuotes(data, config.quoteCharacter) +
143+
config.quoteCharacter;
140144
}
141145
return val;
142146
}
@@ -149,3 +153,17 @@ export const formatData = (config: ConfigOptions, data: any): string => {
149153
}
150154
return data;
151155
};
156+
157+
/**
158+
* If double-quotes are used to enclose fields, then a double-quote
159+
* appearing inside a field must be escaped by preceding it with
160+
* another double quote.
161+
*
162+
* See https://www.rfc-editor.org/rfc/rfc4180
163+
*/
164+
function escapeDoubleQuotes(data: string, quoteCharacter?: string): string {
165+
if (quoteCharacter == '"' && data.indexOf('"') > -1) {
166+
return data.replace(/"/g, '""');
167+
}
168+
return data;
169+
}

0 commit comments

Comments
 (0)
Please sign in to comment.