Socket
Socket
Sign inDemoInstall

csv-to-js-parser

Package Overview
Dependencies
0
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.2.3 to 2.3.0

.editorconfig

338

app.js

@@ -28,3 +28,3 @@ /*

{
if (typeof data !== 'string' ||
if (typeof data !== 'string' ||
(typeof param1 === 'object' && typeof param2 === 'object') ||

@@ -34,3 +34,5 @@ (typeof param1 === 'string' && typeof param2 === 'string') ||

(param2 && (typeof param2 !== 'object' && typeof param2 !== 'string')))
{
throw new Error('Incorrect parameters');
}

@@ -47,7 +49,6 @@ let description;

}
else
else
{
description = param1;
}
}

@@ -69,19 +70,6 @@ if (param2)

//Spliting data by rows
{
//Checking row delimeter
let newRow;
let i = data.indexOf('\n', 0);
if (i === -1) throw new Error('No row delimeter found');
newRow = (data[i - 1] === '\r') ? '\r\n' : '\n';
data = data.split(newRow);
//Deleting last empty row
i = data.length - 1;
while (data[i] === '')
{
data.pop();
i--;
}
}
let header = data[0].split(delimeter);
const dataSplited = splitTiaQuotes(data, delimeter);
let header = dataSplited[0];
data = dataSplited[1];
//Making default description

@@ -93,24 +81,6 @@ if (!description)

{
description[key] = {type: 'string', group: 1};
description[key] = { type: 'string', group: 1 };
}
}
/*
console.log(delimeter);
console.log(description);
*/
//Deleting header from data
data.shift();
//Spliting data by delimeter
{
let newData = [];
for (let row of data)
{
let arr = row.split(delimeter);
newData.push(arr);
}
data = newData;
}
let constantsIndexes = {};

@@ -123,3 +93,3 @@ let constantOrder = [];

{
let index = header.indexOf(key, 0);
let index = header.indexOf(key, 0);
if (index === -1) throw new Error('Cannnot find selected fields in the header');

@@ -130,3 +100,3 @@ if (Number(description[key].group) > 0)

constantsIndexes[key] = index;
constantOrder.push({group: description[key].group, key: key});
constantOrder.push({ group: description[key].group, key: key });
}

@@ -154,3 +124,3 @@ else

return compare(a, b);
}
};
}

@@ -213,3 +183,3 @@ //Sorting constantOrder

let out = [];
if (Object.keys(arraysIndexes).length) //If we have not group columns then we need create arrays in every object. Else we need put equal rows to separate objects.

@@ -220,3 +190,3 @@ {

let obj = {};
for (let key in constantsIndexes)
for (let key in constantsIndexes)
{

@@ -248,3 +218,3 @@ let value = data[i][0][constantsIndexes[key]];

let obj = {};
for (let key in constantsIndexes)
for (let key in constantsIndexes)
{

@@ -260,45 +230,232 @@ let value = data[i][j][constantsIndexes[key]];

/*
function typeInitialisation(type)
function convertToType(value, type)
{
if (value === '') return null;
switch(type.toLowerCase())
{
case 'string':
return '';
case 'number':
return 0;
case 'boolean':
case 'string':
return String(value);
case 'number':
return Number(value);
case 'boolean':
{
let val = value.toLowerCase();
if (val === 'true')
{
return true;
}
else if(val === 'false')
{
return false;
default:
throw new Error('Type is incorrect');
}
else
{
throw new Error('Cannont convert boolean value');
}
}
default:
throw new Error('Type is incorrect');
}
}
*/
function convertToType(value, type)
//Split by delimeter, taking into account double quotes according to rfc4180
function splitTiaQuotes(data, delimeter)
{
if (value === '') return null;
switch(type.toLowerCase())
const dataArray = [];
let header = null;
let rowArray = [];
let dataIndex = 0;
let qPlaceOpen = 0;
let dOrnPlace = 0;
let dPlace = 0;
let rnPlace = 0;
let qPlaceClosed = -1;
let hasNotSpaceSimbolAfterClosingQuotes;
for (;;)
{
case 'string':
return String(value);
case 'number':
return Number(value);
case 'boolean':
let val = value.toLowerCase();
if (val === "true")
if (dPlace >= 0 && dPlace <= dOrnPlace) dPlace = data.indexOf(delimeter, dataIndex);
if (rnPlace >= 0 && rnPlace <= dOrnPlace) rnPlace = data.indexOf('\n', dataIndex);
set_dOrnPlace();
if (qPlaceOpen !== -1 && ((dOrnPlace >= 0 && qPlaceOpen <= dOrnPlace) || dOrnPlace === -1))
{
qPlaceOpen = data.indexOf('"', dataIndex);
qPlaceClosed = qPlaceOpen === -1 ? -1 : data.indexOf('"', qPlaceOpen + 1);
}
if (dOrnPlace === -1) //last field
{
if (qPlaceOpen === -1) //last field without quotes
{
return true;
rowArray.push(data.slice(dataIndex, data.length));
addRowToArray();
break;
}
else if(val === "false")
else if(qPlaceClosed > qPlaceOpen) //last field has more then one quotes
{
return false;
while (data[qPlaceClosed + 1] === '"') //qPlaceClosed refer to escape simbol of "
{
qPlaceClosed = data.indexOf('"', qPlaceClosed + 2);
}
hasNotSpaceSimbolAfterClosingQuotes = false;
for (let i = qPlaceClosed + 1; i < data.length; i++) //After closing quotes and before delimeter we have not space simbols
{
if (data[i] !== ' ')
{
hasNotSpaceSimbolAfterClosingQuotes = true;
break;
}
}
if (hasNotSpaceSimbolAfterClosingQuotes)
{
rowArray.push(data.slice(dataIndex, data.length));
}
else
{
rowArray.push(data.slice(qPlaceOpen + 1, qPlaceClosed).replace(/""/g, '"'));
}
addRowToArray();
break;
}
else //last field has only one qoute
{
rowArray.push(data.slice(dataIndex, data.length));
addRowToArray();
break;
}
}
else if (qPlaceOpen === -1) //no quotes in field;
{
addFieldWithNoQuotes();
dataIndex = dOrnPlace + 1;
addRowToArray();
}
else if (qPlaceOpen < dOrnPlace) //field has quotes
{
let fieldStartsFromQuote;
if (qPlaceOpen === dataIndex)
{
fieldStartsFromQuote = true;
}
else
{
throw new Error('Cannont convert boolean value');
};
default:
throw new Error('Type is incorrect');
fieldStartsFromQuote = true;
for (let i = dataIndex; i < qPlaceOpen; i++)
{
if (data[i] !== ' ')
{
fieldStartsFromQuote = false;
break;
}
}
}
if (fieldStartsFromQuote) //filed start from quote
{
for (;;)
{
if (data[qPlaceClosed + 1] === '"') //qPlaceClosed refer to escape simbol of "
{
qPlaceClosed = data.indexOf('"', qPlaceClosed + 2);
}
else
{
if (dOrnPlace < qPlaceClosed) //dOrnPlace refer to delimeter into escaped filed, for example ""aa, aa
{
if (dPlace < qPlaceClosed) dPlace = data.indexOf(delimeter, qPlaceClosed + 1);
if (rnPlace < qPlaceClosed) rnPlace = data.indexOf('\n', qPlaceClosed + 1);
set_dOrnPlace();
}
break;
}
}
hasNotSpaceSimbolAfterClosingQuotes = false;
for (let i = qPlaceClosed + 1; i < dOrnPlace; i++) //After closing quotes and before delimeter we have not space simbols
{
let s = data[i];
if (!(s === ' ' || s === '\r'))
{
hasNotSpaceSimbolAfterClosingQuotes = true;
break;
}
}
if (hasNotSpaceSimbolAfterClosingQuotes)
{
rowArray.push(data.slice(dataIndex, dOrnPlace));
}
else
{
rowArray.push(data.slice(qPlaceOpen + 1, qPlaceClosed).replace(/""/g, '"'));
}
dataIndex = dOrnPlace + 1;
addRowToArray();
}
else //filed has quote, but not start from quote
{
addFieldWithNoQuotes();
dataIndex = dOrnPlace + 1;
addRowToArray();
}
}
else //filed has not quotes
{
addFieldWithNoQuotes();
dataIndex = dOrnPlace + 1;
addRowToArray();
}
}
//Deleting last empty rows
{
let i = dataArray.length - 1;
while (dataArray[i].length === 1 && dataArray[i][0] === '')
{
dataArray.pop();
i--;
}
}
return [header, dataArray];
function addFieldWithNoQuotes()
{
if (dOrnPlace === rnPlace && data[dOrnPlace - 1] === '\r')
{
rowArray.push(data.slice(dataIndex, dOrnPlace - 1));
}
else
{
rowArray.push(data.slice(dataIndex, dOrnPlace));
}
}
function addRowToArray()
{
if (dOrnPlace === rnPlace)
{
if (header === null)
{
header = rowArray;
}
else
{
dataArray.push(rowArray);
}
rowArray = [];
}
}
function set_dOrnPlace()
{
if (dPlace === -1)
{
dOrnPlace = rnPlace;
}
else if (rnPlace === -1)
{
dOrnPlace = dPlace;
}
else if (rnPlace < dPlace)
{
dOrnPlace = rnPlace;
}
else
{
dOrnPlace = dPlace;
}
}
}

@@ -309,3 +466,3 @@ };

{
if (!Array.isArray(obj)) throw new Error ('Object is not array');
if (!Array.isArray(obj)) throw new Error('Object is not array');
if (!obj[0]) throw new Error('Object error');

@@ -331,3 +488,3 @@ if (!delimeter) delimeter = ',';

{
out += keys[i];
out += needQuotesCheck(keys[i].toString());
if (i !== keys.length - 1) out += delimeter;

@@ -347,3 +504,3 @@ isConstant[i] = !Array.isArray(obj[0][keys[i]]);

let ln = elem[keys[i]].length;
if (maxArrayLength < ln) maxArrayLength = ln;
if (maxArrayLength < ln) maxArrayLength = ln;
}

@@ -361,3 +518,3 @@ }

let val = elem[keys[j]];
if (val !== null) out += val.toString();
if (val !== null) out += needQuotesCheck(val.toString());
}

@@ -367,3 +524,3 @@ else

let val = elem[keys[j]][i];
if (val !== null) out += val.toString();
if (val !== null) out += needQuotesCheck(val.toString());
}

@@ -380,3 +537,3 @@ if (j !== keys.length - 1) out += delimeter;

let val = elem[keys[i]];
if (val !== null) out += val.toString();
if (val !== null) out += needQuotesCheck(val.toString());
if (i !== keys.length - 1) out += delimeter;

@@ -388,2 +545,15 @@ }

return out;
function needQuotesCheck(val)
{
if (val.indexOf('"') === -1)
{
if (val.indexOf(delimeter) === -1 && val.indexOf('\n') === -1) return val;
}
else
{
val = val.replace(/"/g, '""');
}
return `"${val}"`;
}
};

@@ -395,3 +565,3 @@

if (newArrayKeys.length !== arrayKeys.length) throw new Error('Parameters arrayKeys and newArrayKeys should have same length');
if (!Array.isArray(obj)) throw new Error ('Object is not array');
if (!Array.isArray(obj)) throw new Error('Object is not array');
if (!obj[0]) throw new Error('Object error');

@@ -403,3 +573,3 @@ const out = new Array(obj.length);

const elem = obj[index];
if (!Array.isArray(elem[arrayKeys[0]])) throw new Error ('Object array property is not array');
if (!Array.isArray(elem[arrayKeys[0]])) throw new Error('Object array property is not array');
let newKeyObj = new Array(elem[arrayKeys[0]].length);

@@ -414,3 +584,3 @@ for (let i = 0; i < newKeyObj.length; i++) newKeyObj[i] = {};

{
if (!Array.isArray(arr)) throw new Error ('Object array property is not array');
if (!Array.isArray(arr)) throw new Error('Object array property is not array');
if (arr.length !== newKeyObj.length) throw new Error('Arrays have different lengths');

@@ -433,3 +603,3 @@ }

if (newArrayKeys.length !== arrayKeys.length) throw new Error('Parameters arrayKeys and newArrayKeys should have same length');
if (!Array.isArray(obj)) throw new Error ('Object is not array');
if (!Array.isArray(obj)) throw new Error('Object is not array');
if (!obj[0]) throw new Error('Object error');

@@ -442,3 +612,3 @@ const out = new Array(obj.length);

const objArray = elem[objArrayKey];
if (!Array.isArray(objArray)) throw new Error ('Object array property is not array');
if (!Array.isArray(objArray)) throw new Error('Object array property is not array');
for (let keyIndex = 0; keyIndex < arrayKeys.length; keyIndex++)

@@ -445,0 +615,0 @@ {

{
"name": "csv-to-js-parser",
"version": "2.2.3",
"version": "2.3.0",
"description": "Converting csv data into array of JavaScript objects. This module can group input data.",

@@ -5,0 +5,0 @@ "main": "app.js",

@@ -0,1 +1,13 @@

## Версия 2.3. Что нового?
В новой версии была добавлена корректная обработка двойных кавычек (") согласно [rfc4180](https://datatracker.ietf.org/doc/html/rfc4180).
* Теперь значения в полях могут обрамляться кавычками, например
"aaa","bbb"
* Внутри кавычек можно использовать символы разделителя или даже переноса строки:
"aaa,aa","bbb
bb"
* Также поле может содержать сам символ ("), но его нужно предварительно экранировать:
"aaa""aa","bbb""aaa""bb"
* Поля не обрамлённые в двойные кавычки, но содержащие этот символ тоже корректно обработаются:
aa"aa,bb"aaa"bbb
# Преобразование данных csv в объекты JavaScript

@@ -2,0 +14,0 @@

@@ -0,1 +1,13 @@

## Version 2.3. What's new?
The new version added correct handling of double quotes (") according to [rfc4180](https://datatracker.ietf.org/doc/html/rfc4180).
* Values in fields can now be surrounded by quotes, for example
"aaa","bbb"
* Now you can use separator character or even line breaks inside quotes:
"aaa,aa","bbb
bb"
* Also, the field can contain the symbol (") itself, but it must be escaped:
"aaa""aa","bbb""aaa""bb"
* Fields that are not surrounded by double quotes, but containing this characters will also be processed correctly:
aa"aa,bb"aaa"bbb
# Convert csv data to an array of JavaScript objects

@@ -2,0 +14,0 @@

@@ -33,3 +33,2 @@ 'use strict';

const not_normal_csv_sorted =

@@ -98,5 +97,5 @@ `customer_id;customer_name;product;price;closed;customer_status;product_id

`
`;
const not_unique_csv_sorted_1_2 =
const not_unique_csv_sorted_1_2 =
`sex;age;person_id

@@ -125,3 +124,3 @@ female;30;9

const not_unique_csv_sorted_3 =
const not_unique_csv_sorted_3 =
`person_id;sex;age

@@ -150,3 +149,3 @@ 1;male;30

const not_unique_not_normal_csv_sorted_1_2 =
const not_unique_not_normal_csv_sorted_1_2 =
`sex;age;person_id

@@ -175,3 +174,3 @@ female;;9

const not_unique_obj_var1 =
const not_unique_obj_var1 =
[

@@ -280,3 +279,3 @@ {

const not_unique_not_normal_obj_var1 =
const not_unique_not_normal_obj_var1 =
[

@@ -385,5 +384,3 @@ {

const not_unique_obj_var2 =
const not_unique_obj_var2 =
[

@@ -422,3 +419,3 @@ {

const not_unique_not_normal_obj_var2 =
const not_unique_not_normal_obj_var2 =
[

@@ -477,4 +474,3 @@ {

const not_unique_obj_var3 =
const not_unique_obj_var3 =
[

@@ -553,3 +549,3 @@ {

const normal_obj =
const normal_obj =
[

@@ -585,3 +581,3 @@ {

const not_normal_obj =
const not_normal_obj =
[

@@ -617,3 +613,3 @@ {

const normal_obj_with_combine_arrays =
const normal_obj_with_combine_arrays =
[

@@ -703,30 +699,30 @@ {

{
customer_id: {type: 'number', group: 1},
product: {type: 'string'},
product_id: {type: 'number'},
customer_name: {type: 'string', group: 2},
price: {type: 'number'},
closed: {type: 'boolean'},
customer_status: {type: 'number', group: 2}
customer_id: { type: 'number', group: 1 },
product: { type: 'string' },
product_id: { type: 'number' },
customer_name: { type: 'string', group: 2 },
price: { type: 'number' },
closed: { type: 'boolean' },
customer_status: { type: 'number', group: 2 }
};
const not_unique_description_var1 =
const not_unique_description_var1 =
{
age: {type: 'number', group: 1},
sex: {type: 'string', group: 2},
person_id: {type: 'number', group: 3}
age: { type: 'number', group: 1 },
sex: { type: 'string', group: 2 },
person_id: { type: 'number', group: 3 }
};
const not_unique_description_var2 =
const not_unique_description_var2 =
{
age: {type: 'number', group: 1},
sex: {type: 'string', group: 2},
person_id: {type: 'number'}
age: { type: 'number', group: 1 },
sex: { type: 'string', group: 2 },
person_id: { type: 'number' }
};
const not_unique_description_var3 =
const not_unique_description_var3 =
{
age: {type: 'number'},
sex: {type: 'string', group: 2},
person_id: {type: 'number', group: 1}
age: { type: 'number' },
sex: { type: 'string', group: 2 },
person_id: { type: 'number', group: 1 }
};

@@ -749,8 +745,8 @@

}
it ('should return normal object', () => doTest(normal_csv, normal_obj, normal_description));
it ('should return not_normal object', () => doTest(not_normal_csv, not_normal_obj, normal_description));
it ('should return not_unique_obj_var1 object', () => doTest(not_unique_csv, not_unique_obj_var1, not_unique_description_var1));
it ('should return not_unique_obj_var2 object', () => doTest(not_unique_csv, not_unique_obj_var2, not_unique_description_var2));
it ('should return not_unique_obj_var3 object', () => doTest(not_unique_csv, not_unique_obj_var3, not_unique_description_var3));
it ('should return not_unique_obj_var1 object (no description)', () =>
it('should return normal object', () => doTest(normal_csv, normal_obj, normal_description));
it('should return not_normal object', () => doTest(not_normal_csv, not_normal_obj, normal_description));
it('should return not_unique_obj_var1 object', () => doTest(not_unique_csv, not_unique_obj_var1, not_unique_description_var1));
it('should return not_unique_obj_var2 object', () => doTest(not_unique_csv, not_unique_obj_var2, not_unique_description_var2));
it('should return not_unique_obj_var3 object', () => doTest(not_unique_csv, not_unique_obj_var3, not_unique_description_var3));
it('should return not_unique_obj_var1 object (no description)', () =>
{

@@ -778,7 +774,5 @@ //Convert all properties of not_unique_description_var1 to String

const result = app.objToCsv(obj, ';');
const result1 = app.objToCsv(obj, ';');
const result2 = app.objToCsv(obj);
//fs.writeFileSync('expected.csv', expected);
//fs.writeFileSync('result.csv', result);
if (result1 !== expected) throw new Error(`Expected (explicit delimeter):\n${expected}\n\nBut got:\n${result}`);

@@ -800,13 +794,58 @@ let commaExpected = expected.replace(/;/g, ',');

it('should return normal_obj_with_combine_arrays', () =>
{
const result = app.combineArrays(normal_obj, 'products', ['product_id', 'product', 'price', 'closed'], ['product_id', 'name', 'price', 'closed']);
let msg = whereNotEqual(normal_obj_with_combine_arrays, result);
if (msg) throw new Error(msg);
});
{
const result = app.combineArrays(normal_obj, 'products', ['product_id', 'product', 'price', 'closed'], ['product_id', 'name', 'price', 'closed']);
let msg = whereNotEqual(normal_obj_with_combine_arrays, result);
if (msg) throw new Error(msg);
});
it('should return normal_obj', () =>
{
const result = app.separateArrays(normal_obj_with_combine_arrays, 'products', ['product_id', 'name', 'price', 'closed'], ['product_id', 'product', 'price', 'closed']);
let msg = whereNotEqual(normal_obj, result);
if (msg) throw new Error(msg);
});
});
describe('Double quotes specification test (rfc4180)', () =>
{
const csv_for_csvToObj = '"aaa","bb""b",ccc\r\na"aa,"bbb,",",x,"",y\r\nz","yyy"\r\nxx x,yyy"a"y,\r\n"xxx" ,"yyy""a"", y","zzz,a,z"\r\nxxx, "yyy""v,v\r\nay","a, """\r\nzzz,"zz""aaa"z,"zzz"\r\n';
const csv_for_objToCsv = 'aaa,"bb""b",ccc\r\n"a""aa","bbb,",",x,"",y\r\nz"\r\nxx x,"yyy""a""y",\r\nxxx,"yyy""a"", y","zzz,a,z"\r\nxxx,"yyy""v,v\r\nay","a, """\r\nzzz,"""zz""""aaa""z",zzz\r\n';
const obj =
[
{
const result = app.separateArrays(normal_obj_with_combine_arrays, 'products', ['product_id', 'name', 'price', 'closed'], ['product_id', 'product', 'price', 'closed']);
let msg = whereNotEqual(normal_obj, result);
if (msg) throw new Error(msg);
});
aaa: 'a"aa',
'bb"b': 'bbb,',
ccc: ',x,",y\r\nz'
},
{
aaa: 'xx x',
'bb"b': 'yyy"a"y',
ccc: null
},
{
aaa: 'xxx',
'bb"b': 'yyy"a", y',
ccc: 'zzz,a,z'
},
{
aaa: 'xxx',
'bb"b': 'yyy"v,v\r\nay',
ccc: 'a, "'
},
{
aaa: 'zzz',
'bb"b': '"zz""aaa"z',
ccc: 'zzz'
},
];
it('csvToObj should handle double quotes correctly according to rfc 4180', () =>
{
const result = app.csvToObj(csv_for_csvToObj);
const msg = whereNotEqual(obj, result);
if (msg) throw new Error(msg);
});
it('objToCsv should handle double quotes correctly according to rfc 4180', () =>
{
const result = app.objToCsv(obj, ',', 'crlf');
if (result !== csv_for_objToCsv) throw new Error('Returned csv is incorrect.');
});
});

@@ -828,3 +867,3 @@

{
if (typeof(expectedArr[j]) === 'object')
if (typeof (expectedArr[j]) === 'object')
{

@@ -843,3 +882,3 @@ for (let key in expectedArr[j])

{
if (expectedArr[j]!== resultArr[j])
if (expectedArr[j] !== resultArr[j])
{

@@ -846,0 +885,0 @@ flag = true;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc