Repository: mholt/PapaParse (js)

Issue:
Multi-character delimiter and quoted fields
Recently a user reported an issue to me that multi-character delimiter does not work with quoted fields, e.g.

```
a, b, "c, e", d
```
delimiter: `, ` (comma and a single whitespace)

I tried this on the current demo version (on the website): 
```js
Papa.parse('a, b, "c, e", d', {delimiter: ', '})
```
which gives:
```js
'a', 'b', 'c, e", d'
```
expected

```js
'a', 'b', 'c, e', 'd'
```

I also noticed that in the documentation there is always written `delimiting character` but actually multi-character strings are supported (from what I can see in the code and tests).


I think the issue is somewhere around this line: https://github.com/mholt/PapaParse/blob/master/papaparse.js#L1558

```diff
-if (input[quoteSearch + 1 + spacesBetweenQuoteAndDelimiter] === delim)
+if (input.substr(quoteSearch + 1 + spacesBetweenQuoteAndDelimiter, delimLen) === delim)
```

A test could look like this:

```js
{
  description: "Multi-character delimiter (length 2) with quoted field",
  input: 'a, b, "c, e", d',
  config: { delimiter: ", " },
  notes: "The quotes must be immediately adjacent to the delimiter to indicate a quoted field",
  expected: {
    data: [['a', 'b', 'c, e', 'd']],
    errors: []
  }
}
```

Pull request:
Fix #866 - Multi-character delimiter with quoted field issue
Fixes issue #866. I've also added some test for unparsing multi character delimiter where a field contains the delimiter (and needs to be quoted)

Patch:
diff --git a/docs/docs.html b/docs/docs.html
index da3c8b6..c2d82bd 100644
--- a/docs/docs.html
+++ b/docs/docs.html
@@ -303,7 +303,7 @@
 									<code>delimiter</code>
 								</td>
 								<td>
-									The delimiting character. It must not be found in <a href="#readonly">Papa.BAD_DELIMITERS</a>.
+									The delimiting character. Multi-character delimiters are supported. It must not be found in <a href="#readonly">Papa.BAD_DELIMITERS</a>.
 								</td>
 							</tr>
 							<tr>
@@ -470,7 +470,7 @@ var csv = Papa.unparse({
 									<code>delimiter</code>
 								</td>
 								<td>
-									The delimiting character. Leave blank to auto-detect from a list of most common delimiters, or any values passed in through <code>delimitersToGuess</code>. It can be a string or a function. If string, it must be one of length 1. If a function, it must accept the input as first parameter and it must return a string which will be used as delimiter. In both cases it cannot be found in <a href="#readonly">Papa.BAD_DELIMITERS</a>.
+									The delimiting character. Leave blank to auto-detect from a list of most common delimiters, or any values passed in through <code>delimitersToGuess</code>. It can be a string or a function. If a string, it can be of any length (so multi-character delimiters are supported). If a function, it must accept the input as first parameter and it must return a string which will be used as delimiter. In both cases it cannot be found in <a href="#readonly">Papa.BAD_DELIMITERS</a>.
 								</td>
 							</tr>
 							<tr>
@@ -861,7 +861,7 @@ var csv = Papa.unparse({
 							<tr>
 								<td><code>Papa.BAD_DELIMITERS</code></td>
 								<td>
-									An array of characters that are not allowed as delimiters.
+									An array of characters that are not allowed as delimiters (<code>\r, \n, ", \ufeff</code>).
 								</td>
 							</tr>
 							<tr>
diff --git a/papaparse.js b/papaparse.js
index 090c663..057a16c 100755
--- a/papaparse.js
+++ b/papaparse.js
@@ -1555,7 +1555,7 @@ License: MIT
 						var spacesBetweenQuoteAndDelimiter = extraSpaces(checkUpTo);
 
 						// Closing quote followed by delimiter or 'unnecessary spaces + delimiter'
-						if (input[quoteSearch + 1 + spacesBetweenQuoteAndDelimiter] === delim)
+						if (input.substr(quoteSearch + 1 + spacesBetweenQuoteAndDelimiter, delimLen) === delim)
 						{
 							row.push(input.substring(cursor, quoteSearch).replace(quoteCharRegex, quoteChar));
 							cursor = quoteSearch + 1 + spacesBetweenQuoteAndDelimiter + delimLen;


Test patch:
diff --git a/tests/test-cases.js b/tests/test-cases.js
index d727bfe..0c3a62d 100644
--- a/tests/test-cases.js
+++ b/tests/test-cases.js
@@ -847,6 +847,16 @@ var PARSE_TESTS = [
 			errors: []
 		}
 	},
+	{
+		description: "Multi-character delimiter (length 2) with quoted field",
+		input: 'a, b, "c, e", d',
+		config: { delimiter: ", " },
+		notes: "The quotes must be immediately adjacent to the delimiter to indicate a quoted field",
+		expected: {
+			data: [['a', 'b', 'c, e', 'd']],
+			errors: []
+		}
+	},
 	{
 		description: "Callback delimiter",
 		input: 'a$ b$ c',
@@ -1713,6 +1723,12 @@ var UNPARSE_TESTS = [
 		config: { delimiter: ', ' },
 		expected: 'A, b, c\r\nd, e, f'
 	},
+	{
+		description: "Custom delimiter (Multi-character), field contains custom delimiter",
+		input: [['A', 'b', 'c'], ['d', 'e', 'f, g']],
+		config: { delimiter: ', ' },
+		expected: 'A, b, c\r\nd, e, "f, g"'
+	},
 	{
 		description: "Bad delimiter (\\n)",
 		notes: "Should default to comma",