Skip to content

Commit

Permalink
Merge pull request #25 from doug-martin/master
Browse files Browse the repository at this point in the history
v0.2.2
  • Loading branch information
doug-martin committed Mar 18, 2014
2 parents dea9a9d + 4b489d2 commit 63f5f1d
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 6 deletions.
9 changes: 5 additions & 4 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ function createParser(options) {
VALUE_REGEXP = new RegExp("([^" + delimiter + "'\"\\s\\\\]*(?:\\s+[^" + delimiter + "'\"\\s\\\\]+)*)"),
SEARCH_REGEXP = new RegExp("(?:\\n|\\r|" + delimiter + ")"),
ESCAPE_CHAR = options.escape || '"',
NEXT_TOKEN_REGEXP = new RegExp("([^\\s]|\\n|\\r|" + delimiter + ")"),
LINE_BREAK = /[\r\n]/;
NEXT_TOKEN_REGEXP = new RegExp("([^\\s]|\\r\\n|\\n|\\r|" + delimiter + ")"),
LINE_BREAK = /(\r\n|\n|\r)/;

function formatItem(item) {
if (doTrim) {
Expand Down Expand Up @@ -112,9 +112,10 @@ function createParser(options) {
}

function getNextToken(line, cursor) {
var token, nextIndex;
if ((nextIndex = line.substr(cursor).search(NEXT_TOKEN_REGEXP)) !== -1) {
var token, nextIndex, subStr = line.substr(cursor);
if ((nextIndex = subStr.search(NEXT_TOKEN_REGEXP)) !== -1) {
token = line[cursor += nextIndex];
cursor += subStr.match(NEXT_TOKEN_REGEXP)[1].length - 1;
}
return {token: token, cursor: cursor};
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fast-csv",
"version": "0.2.1",
"version": "0.2.2",
"description": "CSV parser and writer",
"main": "index.js",
"scripts": {
Expand Down
200 changes: 199 additions & 1 deletion test/parser.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ it.describe("fast-csv parser", function (it) {
});
});
});

});

it.describe("with \\r", function (it) {
Expand Down Expand Up @@ -402,4 +401,203 @@ it.describe("fast-csv parser", function (it) {

});

it.describe("with \\r\\n", function (it) {

it.describe("unescaped data", function (it) {

it.should("parse a block of CSV text", function () {
var data = "first_name,last_name,email_address\r\nFirst1,Last1,[email protected]";
var myParser = parser({delimiter: ","});
assert.deepEqual(myParser(data, false), {"line": "", "rows": [
["first_name", "last_name", "email_address"],
["First1", "Last1", "[email protected]"]
]});
});

it.should("return the rest of the line if there is more data", function () {
var data = "first_name,last_name,email_address\r\nFirst1,Last1,[email protected]";
var myParser = parser({delimiter: ","});
assert.deepEqual(myParser(data, true), {
"line": "First1,Last1,[email protected]",
"rows": [
["first_name", "last_name", "email_address"]
]
});
});

it.should("accept new data and return the result", function () {
var data = "first_name,last_name,email_address\r\nFirst1,Last1,[email protected],";
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": "First1,Last1,[email protected],",
"rows": [
["first_name", "last_name", "email_address"]
]
});
assert.deepEqual(myParser(parsedData.line + "\r\nFirst2,Last2,[email protected]", false), {"line": "", "rows": [
["First1", "Last1", "[email protected]"],
["First2", "Last2", "[email protected]"]
]});
});

it.should("not parse a row if a new line is not found and there is more data", function () {
var data = "first_name,last_name,email_address";
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": "first_name,last_name,email_address",
"rows": []
});
});

it.should("not parse a row if there is a trailing delimiter and there is more data", function () {
var data = "first_name,last_name,email_address,";
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": "first_name,last_name,email_address,",
"rows": []
});
});

it.should("parse a row if a new line is found and there is more data", function () {
var data = "first_name,last_name,email_address\r\n";
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": "",
"rows": [
["first_name", "last_name", "email_address"]
]
});
});

});

it.describe("escaped values", function (it) {

it.should("parse a block of CSV text", function () {
var data = 'first_name,last_name,email_address\r\n"First,1","Last,1","[email protected]"';
var myParser = parser({delimiter: ","});
assert.deepEqual(myParser(data, false), {"line": "", "rows": [
["first_name", "last_name", "email_address"],
["First,1", "Last,1", "[email protected]"]
]});
});

it.should("parse a block of CSV text with escaped escaped char", function () {
var data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","[email protected]"';
var myParser = parser({delimiter: ","});
assert.deepEqual(myParser(data, false), {"line": "", "rows": [
["first_name", "last_name", "email_address"],
["First,\"1\"", "Last,\"1\"", "[email protected]"]
]});
});

it.should("parse a block of CSV text with alternate escape char", function () {
var data = 'first_name,last_name,email_address\r\n"First,\\"1\\"","Last,\\"1\\"","[email protected]"';
var myParser = parser({delimiter: ",", escape: "\\"});
assert.deepEqual(myParser(data, false), {"line": "", "rows": [
["first_name", "last_name", "email_address"],
["First,\"1\"", "Last,\"1\"", "[email protected]"]
]});
});

it.should("return the rest of the line if a complete value is not found", function () {
var data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","[email protected]';
var myParser = parser({delimiter: ","});
assert.deepEqual(myParser(data, true), {
"line": '"First,""1""","Last,""1""","[email protected]',
"rows": [
["first_name", "last_name", "email_address"]
]
});
});

it.should("accept more data appended to the returned line with escaped values", function () {
var data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","[email protected]';
var myParser = parser({delimiter: ","}),
parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": '"First,""1""","Last,""1""","[email protected]',
"rows": [
["first_name", "last_name", "email_address"]
]
});
assert.deepEqual(myParser(parsedData.line + '"\r\n"First,""2""","Last,""2""","[email protected]"', false), {
line: "",
rows: [
["First,\"1\"", "Last,\"1\"", "[email protected]"],
["First,\"2\"", "Last,\"2\"", "[email protected]"]
]
});
});

it.should("throw an error if there is not more data and there is an invalid escape sequence", function () {
var data = 'first_name,last_name,email_address\r\n"First,""1""","Last,""1""","[email protected]';
var myParser = parser({delimiter: ","}),
parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": '"First,""1""","Last,""1""","[email protected]',
"rows": [
["first_name", "last_name", "email_address"]
]
});
assert.throws(function () {
assert.deepEqual(myParser(parsedData.line + '\r\n"First,"",2""","Last""2""","[email protected]"', false), {
line: "",
rows: [
["First,\"1\"", "Last,\"1\"", "[email protected]"],
["First,\"2\"", "Last,\"2\"", "[email protected]"]
]
});
}, Error, ' Parse Error: expected: \'"\' got: \'F\'. at \'First,""2""","Last""2""","[email protected]"');
});

it.should("handle empty values properly", function () {
var data = '"","",""\r\n,Last4,[email protected]';
var myParser = parser({delimiter: ","}),
parsedData = myParser(data, false);
assert.deepEqual(parsedData, {"line": "", "rows": [
["", "", ""],
["", "Last4", "[email protected]"]
]});
});

it.should("not parse a row if a new line is not found and there is more data", function () {
var data = '"first_name","last_name","email_address"';
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": '"first_name","last_name","email_address"',
"rows": []
});
});

it.should("not parse a row if there is a trailing delimiter and there is more data", function () {
var data = '"first_name","last_name","email_address",';
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": '"first_name","last_name","email_address",',
"rows": []
});
});

it.should("parse a row if a new line is found and there is more data", function () {
var data = '"first_name","last_name","email_address"\r\n';
var myParser = parser({delimiter: ","});
var parsedData = myParser(data, true);
assert.deepEqual(parsedData, {
"line": "",
"rows": [
["first_name", "last_name", "email_address"]
]
});
});
});

});

});

0 comments on commit 63f5f1d

Please sign in to comment.