Skip to content

Commit

Permalink
feat: add unicode chars to formula escape (#387)
Browse files Browse the repository at this point in the history
* fix(csv-stringify): use switch in formula escaping

* fix(csv-stringify): add unicode character equivalents in formula sanitization

* chore: update tests
  • Loading branch information
tomemelko committed May 9, 2023
1 parent fbff146 commit 1fc177c
Show file tree
Hide file tree
Showing 18 changed files with 266 additions and 35 deletions.
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/cjs/index.cjs
Expand Up @@ -475,8 +475,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/cjs/sync.cjs
Expand Up @@ -473,8 +473,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/esm/index.js
Expand Up @@ -5533,8 +5533,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/esm/sync.js
Expand Up @@ -2443,8 +2443,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/iife/index.js
Expand Up @@ -5536,8 +5536,21 @@ var csv_stringify = (function (exports) {
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/iife/sync.js
Expand Up @@ -2446,8 +2446,21 @@ var csv_stringify_sync = (function (exports) {
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/umd/index.js
Expand Up @@ -5539,8 +5539,21 @@
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/dist/umd/sync.js
Expand Up @@ -2449,8 +2449,21 @@
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv-stringify/lib/api/index.js
Expand Up @@ -158,8 +158,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
12 changes: 11 additions & 1 deletion packages/csv-stringify/test/option.escape_formulas.coffee
Expand Up @@ -19,7 +19,7 @@ describe 'Option `escape_formulas`', ->
code: 'CSV_OPTION_ESCAPE_FORMULAS_INVALID_TYPE'
message: 'option `escape_formulas` must be a boolean, got "invalid"'

it 'escape =, +, -, @, \\t, \\r signs', (next) ->
it 'escape =, +, -, @, \\t, \\r and unicode equivalent signs', (next) ->
stringify [
[ '=a',1]
[ '+b',2]
Expand All @@ -28,6 +28,11 @@ describe 'Option `escape_formulas`', ->
[ '\te',5]
[ '\rf',6]
[ 'g',7]
[ '\uFF1Dh',8]
[ '\uFF0Bi',9]
[ '\uFF0Dj',10]
[ '\uFF20k',11]
[ '\uFF0Cl',12] # \uFF0C is 'full width comma' and should not be escaped
], escape_formulas: true, eof: false, (err, data) ->
return next err if err
data.should.eql """
Expand All @@ -38,6 +43,11 @@ describe 'Option `escape_formulas`', ->
'\te,5
'\rf,6
g,7
'\uFF1Dh,8
'\uFF0Bi,9
'\uFF0Dj,10
'\uFF20k,11
\uFF0Cl,12
"""
next()

Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/cjs/index.cjs
Expand Up @@ -2271,8 +2271,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/cjs/sync.cjs
Expand Up @@ -2048,8 +2048,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/esm/index.js
Expand Up @@ -7398,8 +7398,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/esm/sync.js
Expand Up @@ -7175,8 +7175,21 @@ const stringifier = function(options, state, info){
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/iife/index.js
Expand Up @@ -7401,8 +7401,21 @@ var csv = (function (exports) {
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down
17 changes: 15 additions & 2 deletions packages/csv/dist/iife/sync.js
Expand Up @@ -7178,8 +7178,21 @@ var csv_sync = (function (exports) {
}
});
quotedMatch = quotedMatch && quotedMatch.length > 0;
if (escape_formulas && ['=', '+', '-', '@', '\t', '\r'].includes(value[0])) {
value = `'${value}`;
if (escape_formulas) {
switch (value[0]) {
case '=':
case '+':
case '-':
case '@':
case '\t':
case '\r':
case '\uFF1D': // Unicode '='
case '\uFF0B': // Unicode '+'
case '\uFF0D': // Unicode '-'
case '\uFF20': // Unicode '@'
value = `'${value}`;
break;
}
}
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch;
if(shouldQuote === true && containsEscape === true){
Expand Down

0 comments on commit 1fc177c

Please sign in to comment.