Repository: mholt/PapaParse (js)

Issue:
Undetectable Delimiter error for local files ending with a empty line, even if skipEmptyLines is true
By default excel adds a empty line at the end of exported csv files. If you try to parse these with the local file function and auto detect delimiter you'll end up with an "Undetectable Delimiter" error. Even if you enable skipEmptyLines you'll get the error. 

It can be reproduced with the demo on your website and the attached file.
[Mappe1.zip](https://github.com/mholt/PapaParse/files/236626/Mappe1.zip)


Pull request:
Skip correctly empty lines while detecting delimiter, fixes #309
Parsing was broken with newline-terminated short data with `delimiter: auto` and `skipEmptyLines: true`, as described in #309.

Test added in first commit, failed with the following error:

<img width="1414" alt="screen shot 2017-07-13 at 12 03 48 pm" src="https://user-images.githubusercontent.com/1799710/28161363-914410d8-67c3-11e7-95fb-afd47257e9c8.png">

Second commit fixes the bug and passes the test.

Patch:
diff --git a/papaparse.js b/papaparse.js
index e95da93..63c2c1c 100644
--- a/papaparse.js
+++ b/papaparse.js
@@ -878,7 +878,7 @@
 			_delimiterError = false;
 			if (!_config.delimiter)
 			{
-				var delimGuess = guessDelimiter(input, _config.newline);
+				var delimGuess = guessDelimiter(input, _config.newline, _config.skipEmptyLines);
 				if (delimGuess.successful)
 					_config.delimiter = delimGuess.bestDelimiter;
 				else
@@ -1040,7 +1040,7 @@
 			return _results;
 		}
 
-		function guessDelimiter(input, newline)
+		function guessDelimiter(input, newline, skipEmptyLines)
 		{
 			var delimChoices = [',', '\t', '|', ';', Papa.RECORD_SEP, Papa.UNIT_SEP];
 			var bestDelim, bestDelta, fieldCountPrevRow;
@@ -1048,7 +1048,7 @@
 			for (var i = 0; i < delimChoices.length; i++)
 			{
 				var delim = delimChoices[i];
-				var delta = 0, avgFieldCount = 0;
+				var delta = 0, avgFieldCount = 0, emptyLinesCount = 0;
 				fieldCountPrevRow = undefined;
 
 				var preview = new Parser({
@@ -1059,6 +1059,10 @@
 
 				for (var j = 0; j < preview.data.length; j++)
 				{
+					if (skipEmptyLines && preview.data[j].length === 1 && preview.data[j][0].length === 0) {
+						emptyLinesCount++
+						continue
+					}
 					var fieldCount = preview.data[j].length;
 					avgFieldCount += fieldCount;
 
@@ -1075,7 +1079,7 @@
 				}
 
 				if (preview.data.length > 0)
-					avgFieldCount /= preview.data.length;
+					avgFieldCount /= (preview.data.length - emptyLinesCount);
 
 				if ((typeof bestDelta === 'undefined' || delta < bestDelta)
 					&& avgFieldCount > 1.99)


Test patch:
diff --git a/tests/test-cases.js b/tests/test-cases.js
index 5ae3afb..1b857c4 100644
--- a/tests/test-cases.js
+++ b/tests/test-cases.js
@@ -919,6 +919,16 @@ var PARSE_TESTS = [
 			errors: []
 		}
 	},
+	{
+		description: "Skip empty lines while detecting delimiter",
+		notes: "Parsing correctly newline-terminated short data with delimiter:auto and skipEmptyLines:true",
+		input: 'a,b\n1,2\n3,4\n',
+		config: { header: true, skipEmptyLines: true },
+		expected: {
+			data: [{'a': '1', 'b': '2'}, {'a': '3', 'b': '4'}],
+			errors: []
+		}
+	},
 	{
 		description: "Single quote as quote character",
 		notes: "Must parse correctly when single quote is specified as a quote character",