diff --git a/README.md b/README.md index 4c179fa..8052db6 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ Robust, efficient CSV parsing (supports custom delimiting characters). Malformed **[jsFIDDLE DEMO](http://jsfiddle.net/mholt/nCaee/)** +Most people will want to use the minified [jquery.parse.min.js](https://github.com/mholt/jquery.parse/blob/master/jquery.parse.min.js) file. + +For debug and development, feel free to use the original [jquery.parse.js](https://github.com/mholt/jquery.parse/blob/master/jquery.parse.js) file. + +This project is under test. Download this repository and open `tests.html` in your browser to run them. + Basic usage ----------- @@ -102,10 +108,12 @@ Here is the structure of an error: ```javascript { - message: "", // Human-readable message - line: 0, // Line of original input - row: 0, // Row index where error was - index: 0 // Character index within original input + type: "", // Either "Quotes" or "FieldMismatch" + code: "", // Standardized error code like "UnexpectedQuotes" + message: "", // Human-readable error details + line: 0, // Line of original input + row: 0, // Row index of parsed data where error is + index: 0 // Character index within original input } ``` @@ -135,12 +143,16 @@ Notice the stray quotes on the second line. This is the output: }, "errors": [ { + "type": "FieldMismatch", + "code": "TooFewFields", "message": "Too few fields; expected 4 fields, parsed 2", "line": 2, "row": 0, "index": 66 }, { + "type": "Quotes", + "code": "MissingQuotes", "message": "Unescaped or mismatched quotes", "line": 2, "row": 0, @@ -168,6 +180,8 @@ If the header row is disabled, field counting does not occur, because there is n ], "errors": [ { + "type": "Quotes", + "code": "MissingQuotes", "message": "Unescaped or mismatched quotes", "line": 2, "row": 1, @@ -216,13 +230,17 @@ Again, notice the second line, "10,95" instead of "10.95". This field *should* b }, "errors": [ { - "message": "Too many fields; expected 4 fields, found extra value: '4'", + "type": "FieldMismatch", + "code": "TooManyFields", + "message": "Too many fields: expected 4 fields but parsed 5", "line": 2, "row": 0, "index": 43 }, { - "message": "Too few fields; expected 4 fields, parsed 5", + "type": "FieldMismatch", + "code": "TooFewFields", + "message": "Too few fields: expected 4 fields but parsed 5", "line": 2, "row": 0, "index": 43 diff --git a/jquery.parse.js b/jquery.parse.js index 1713a90..0ee89b6 100644 --- a/jquery.parse.js +++ b/jquery.parse.js @@ -1,6 +1,6 @@ /* jQuery Parse Plugin - v0.5.9 + v0.6.0 https://github.com/mholt/jquery.parse */ @@ -82,7 +82,7 @@ endRow(); if (_state.inQuotes) - addError("Unescaped or mismatched quotes"); + addError("Quotes", "MissingQuotes", "Unescaped or mismatched quotes"); return self.getParsed(); }; @@ -156,9 +156,9 @@ function handleQuote() { - var delimBefore = (_state.i > 0 && isBoundary(_input[_state.i-1])) + var delimBefore = (_state.i > 0 && isBoundary(_state.i-1)) || _state.i == 0; - var delimAfter = (_state.i < _input.length - 1 && isBoundary(_input[_state.i+1])) + var delimAfter = (_state.i < _input.length - 1 && isBoundary(_state.i+1)) || _state.i == _input.length - 1; var escaped = _state.i < _input.length - 1 && _input[_state.i+1] == '"'; @@ -174,7 +174,7 @@ } else { - addError("Unexpected quotes"); + addError("Quotes", "UnexpectedQuotes", "Unexpected quotes"); } } @@ -204,9 +204,30 @@ appendCharToField(); } - function isBoundary(ch) + function isBoundary(i) { - return ch == _config.delimiter || ch == "\n"; + if (i >= _input.length) + return false; + + var ch = _input[i]; + + if (ch == _config.delimiter + || ch == "\n" + || (ch == "\r" && i < _input.length - 1 && _input[i+1] == "\n")) + return true; + else + return false; + } + + function isLineEnding(i) + { + if (i >= _input.length) + return false; + + if (i < _input.length - 1) + return _input[i] == "\n" || (_input[i] == "\r" && _input[i+1] == "\n"); + else + return _input[i] == "\n"; } function saveField() @@ -230,7 +251,6 @@ if (typeof currentRow.__parsed_extra === 'undefined') currentRow.__parsed_extra = []; currentRow.__parsed_extra.push(_state.fieldVal); - addError("Too many fields; expected " + _state.parsed.fields.length + " fields, found extra value: '" + _state.fieldVal + "'"); } } } @@ -312,15 +332,18 @@ if (lastRow.hasOwnProperty(prop)) actual ++; - if (expected != actual) - return addError("Too few fields; expected " + expected + " fields, parsed " + actual); - + if (actual < expected) + return addError("FieldMismatch", "TooFewFields", "Too few fields: expected " + expected + " fields but parsed " + actual); + else if (actual > expected) + return addError("FieldMismatch", "TooManyFields", "Too many fields: expected " + expected + " fields but parsed " + actual); return true; } - function addError(msg) + function addError(type, code, msg) { _errors.push({ + type: type, + code: code, message: msg, line: _state.lineNum, row: _config.header ? _state.parsed.rows.length - 1 : _state.parsed.length - 1, diff --git a/jquery.parse.min.js b/jquery.parse.min.js index db2ae5e..b4513b7 100644 --- a/jquery.parse.min.js +++ b/jquery.parse.min.js @@ -1,6 +1,6 @@ /* jQuery Parse Plugin - v0.5.9 + v0.6.0 https://github.com/mholt/jquery.parse */ -;(function(e){"use strict";function n(e){e.delimiter=e.delimiter||t.delimiter;e.header=typeof e.header==="undefined"?t.header:e.header;e.dynamicTyping=typeof e.dynamicTyping==="undefined"?t.dynamicTyping:e.dynamicTyping;if(e.delimiter=='"'||e.delimiter=="\n")e.delimiter=t.delimiter;if(e.delimiter.length>1)e.delimiter=e.delimiter[0];return e}function r(e,t){function a(e){return e?{fields:[],rows:[]}:[[]]}function f(){return{i:0,lineNum:1,field:0,fieldVal:"",line:"",ch:"",inQuotes:false,parsed:a(t.header)}}function l(){var e=u.i>0&&d(r[u.i-1])||u.i==0;var t=u.i0)u.parsed.rows.push({});else u.parsed.push([]);u.lineNum++;u.line="";u.field=0}function y(e){var t=o.floats.test(e);return t?parseFloat(e):e}function b(){if(o.empty.test(u.line)){if(i.header){if(u.lineNum==1){u.parsed.fields=[];u.lineNum--}else u.parsed.rows.splice(u.parsed.rows.length-1,1)}else u.parsed.splice(u.parsed.length-1,1);return true}return false}function w(){if(!i.header)return true;if(u.parsed.rows.length==0)return true;var e=u.parsed.fields.length;var t=0;var n=u.parsed.rows[u.parsed.rows.length-1];for(var r in n)if(n.hasOwnProperty(r))t++;if(e!=t)return E("Too few fields; expected "+e+" fields, parsed "+t);return true}function E(e){s.push({message:e,line:u.lineNum,row:i.header?u.parsed.rows.length-1:u.parsed.length-1,index:u.i});return false}var n=this;var r=e;var i=t;var s=[];var o={floats:/^-?\d+(\.\d+)?$/,empty:/^\s*$/};var u=f();this.parse=function(e){if(typeof e==="object")n.setConfig(e);else if(typeof e==="string")n.setInput(e);s=[];u=f();for(u.i=0;u.i1)e.delimiter=e.delimiter[0];return e}function r(e,t){function a(e){return e?{fields:[],rows:[]}:[[]]}function f(){return{i:0,lineNum:1,field:0,fieldVal:"",line:"",ch:"",inQuotes:false,parsed:a(t.header)}}function l(){var e=u.i>0&&d(u.i-1)||u.i==0;var t=u.i=r.length)return false;var t=r[e];if(t==i.delimiter||t=="\n"||t=="\r"&&e=r.length)return false;if(e0)u.parsed.rows.push({});else u.parsed.push([]);u.lineNum++;u.line="";u.field=0}function b(e){var t=o.floats.test(e);return t?parseFloat(e):e}function w(){if(o.empty.test(u.line)){if(i.header){if(u.lineNum==1){u.parsed.fields=[];u.lineNum--}else u.parsed.rows.splice(u.parsed.rows.length-1,1)}else u.parsed.splice(u.parsed.length-1,1);return true}return false}function E(){if(!i.header)return true;if(u.parsed.rows.length==0)return true;var e=u.parsed.fields.length;var t=0;var n=u.parsed.rows[u.parsed.rows.length-1];for(var r in n)if(n.hasOwnProperty(r))t++;if(te)return S("FieldMismatch","TooManyFields","Too many fields: expected "+e+" fields but parsed "+t);return true}function S(e,t,n){s.push({type:e,code:t,message:n,line:u.lineNum,row:i.header?u.parsed.rows.length-1:u.parsed.length-1,index:u.i});return false}var n=this;var r=e;var i=t;var s=[];var o={floats:/^-?\d+(\.\d+)?$/,empty:/^\s*$/};var u=f();this.parse=function(e){if(typeof e==="object")n.setConfig(e);else if(typeof e==="string")n.setInput(e);s=[];u=f();for(u.i=0;u.i