@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
/ *
Papa Parse
v3 . 0. 1
v3 . 1.0
https : //github.com/mholt/PapaParse
* /
( function ( global )
@ -21,6 +21,7 @@
@@ -21,6 +21,7 @@
worker : false ,
comments : false ,
complete : undefined ,
error : undefined ,
download : false ,
chunk : undefined ,
keepEmptyRows : false
@ -40,6 +41,7 @@
@@ -40,6 +41,7 @@
// Configurable chunk sizes for local and remote files, respectively
global . Papa . LocalChunkSize = 1024 * 1024 * 10 ; // 10 MB
global . Papa . RemoteChunkSize = 1024 * 1024 * 5 ; // 5 MB
global . Papa . DefaultDelimiter = "," ; // Used if not specified and detection fails
// Exposed for testing and development only
global . Papa . Parser = Parser ;
@ -81,11 +83,7 @@
@@ -81,11 +83,7 @@
function parseNextFile ( )
{
if ( queue . length == 0 )
{
if ( isFunction ( options . complete ) )
options . complete ( ) ;
return ;
}
var f = queue [ 0 ] ;
@ -189,8 +187,6 @@
@@ -189,8 +187,6 @@
{
var ph = new ParserHandle ( config ) ;
var results = ph . parse ( _input ) ;
if ( isFunction ( config . complete ) )
config . complete ( results ) ;
return results ;
}
}
@ -218,8 +214,6 @@
@@ -218,8 +214,6 @@
{
var ph = new ParserHandle ( config ) ;
var results = ph . parse ( event . target . result ) ;
if ( isFunction ( config . complete ) )
config . complete ( results ) ;
} ;
reader . onerror = function ( )
{
@ -364,7 +358,7 @@
@@ -364,7 +358,7 @@
// Encloses a value around quotes if needed (makes a value safe for CSV insertion)
function safe ( str , col )
{
if ( typeof str === "undefined" )
if ( typeof str === "undefined" || str === null )
return "" ;
str = str . toString ( ) . replace ( /"/g , '""' ) ;
@ -390,7 +384,7 @@
@@ -390,7 +384,7 @@
// NOTE/ TODO: Many of the functions of NetworkStreamer and FileStreamer are the same. Consolidate?
// TODO: Many of the functions of NetworkStreamer and FileStreamer are similar or the same. Consolidate?
function NetworkStreamer ( config )
{
config = config || { } ;
@ -498,15 +492,11 @@
@@ -498,15 +492,11 @@
}
else if ( isFunction ( config . chunk ) )
{
config . chunk ( results ) ; // TODO: Implement abort? (like step)
config . chunk ( results ) ;
results = undefined ;
}
if ( finishedWithEntireFile && isFunction ( config . complete ) )
config . complete ( results ) ;
else if ( results && results . meta . aborted && isFunction ( config . complete ) )
config . complete ( results ) ;
else if ( ! finishedWithEntireFile )
if ( ! finishedWithEntireFile && ! results . meta . paused )
nextChunk ( ) ;
}
@ -545,7 +535,7 @@
@@ -545,7 +535,7 @@
config = config || { } ;
if ( ! config . chunkSize )
config . chunkSize = Papa . LocalChunkSize ;
var start = 0 ;
var aggregate = "" ;
var partialLine = "" ;
@ -633,12 +623,8 @@
@@ -633,12 +623,8 @@
config . chunk ( results , file ) ;
results = undefined ;
}
if ( finishedWithEntireFile && isFunction ( config . complete ) )
config . complete ( undefined , file ) ;
else if ( results && results . meta . aborted && isFunction ( config . complete ) ) // TODO: Abort needs reworking like pause/resume need it (if streaming, no results object is returned, so it has no meta to say aborted: true...)
config . complete ( results , file ) ;
else if ( ! finishedWithEntireFile )
if ( ! finishedWithEntireFile && ! results . meta . paused )
nextChunk ( ) ;
}
@ -669,6 +655,10 @@
@@ -669,6 +655,10 @@
// One goal is to minimize the use of regular expressions...
var FLOAT = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i ;
var self = this ;
var _input ; // The input being parsed
var _parser ; // The core parser being used
var _paused = false ; // Whether we are paused or not
var _delimiterError ; // Temporary state between delimiter detection and processing results
var _fields = [ ] ; // Fields are from the header row of the input, if there is one
var _results = { // The last results returned from the parser
@ -689,7 +679,7 @@
@@ -689,7 +679,7 @@
else
{
_delimiterError = true ; // add error after parsing (otherwise it would be overwritten)
_config . delimiter = "," ;
_config . delimiter = Papa . DefaultDelimiter ;
}
_results . meta . delimiter = _config . delimiter ;
}
@ -697,25 +687,57 @@
@@ -697,25 +687,57 @@
if ( isFunction ( _config . step ) )
{
var userStep = _config . step ;
_config . step = function ( results , parser )
_config . step = function ( results )
{
_results = results ;
if ( needsHeaderRow ( ) )
processResults ( ) ;
else
userStep ( processResults ( ) , parser ) ;
userStep ( processResults ( ) , self ) ;
} ;
}
_results = new Parser ( _config ) . parse ( input ) ;
return processResults ( ) ;
if ( _config . preview && _config . header )
_config . preview ++ ; // to compensate for header row
_input = input ;
_parser = new Parser ( _config ) ;
_results = _parser . parse ( _input ) ;
processResults ( ) ;
if ( isFunction ( _config . complete ) && ! _paused )
_config . complete ( _results ) ;
return _paused ? { meta : { paused : true } } : _results ;
} ;
this . pause = function ( )
{
_paused = true ;
_parser . abort ( ) ;
_input = _input . substr ( _parser . getCharIndex ( ) ) ;
} ;
this . resume = function ( )
{
_paused = false ;
_parser = new Parser ( _config ) ;
_parser . parse ( _input ) ;
if ( isFunction ( _config . complete ) && ! _paused )
_config . complete ( _results ) ;
} ;
this . abort = function ( )
{
_parser . abort ( ) ;
if ( isFunction ( _config . complete ) )
_config . complete ( _results ) ;
_input = "" ;
}
function processResults ( )
{
if ( _results && _delimiterError )
{
addError ( "Delimiter" , "UndetectableDelimiter" , "Unable to auto-detect delimiting character; defaulted to comma" ) ;
addError ( "Delimiter" , "UndetectableDelimiter" , "Unable to auto-detect delimiting character; defaulted to '" + Papa . DefaultDelimiter + "' " ) ;
_delimiterError = false ;
}
@ -869,7 +891,6 @@
@@ -869,7 +891,6 @@
function Parser ( config )
{
var self = this ;
var EMPTY = /^\s*$/ ;
var _input ; // The input text being parsed
@ -888,7 +909,6 @@
@@ -888,7 +909,6 @@
var _colIdx ; // Current col index within result row (0-based)
var _runningRowIdx ; // Cumulative row index, used by the preview feature
var _aborted = false ; // Abort flag
var _paused = false ; // Pause flag
// Unpack the config object
config = config || { } ;
@ -920,35 +940,24 @@
@@ -920,35 +940,24 @@
reset ( input ) ;
return parserLoop ( ) ;
} ;
/ *
// TODO: Pause and resume just doesn't work well.
// I suspect this may need to be implemented at a higher-level
// scope than just this core Parser.
this . pause = function ( )
{
_paused = true ;
} ;
this . resume = function ( )
{
_paused = false ;
if ( _i < _input . length )
return parserLoop ( ) ;
} ;
* /
this . abort = function ( )
{
_aborted = true ;
} ;
this . getCharIndex = function ( )
{
return _i ;
} ;
function parserLoop ( )
{
while ( _i < _input . length )
{
if ( _aborted ) break ;
if ( _preview > 0 && _runningRowIdx >= _preview ) break ;
if ( _paused ) return finishParsing ( ) ;
if ( _ch == '"' )
parseQuotes ( ) ;
else if ( _inQuotes )
@ -1066,7 +1075,7 @@
@@ -1066,7 +1075,7 @@
if ( isFunction ( _step ) )
{
if ( _data [ _rowIdx ] )
_step ( returnable ( ) , self ) ;
_step ( returnable ( ) ) ;
clearErrorsAndData ( ) ;
}
}
@ -1085,7 +1094,7 @@
@@ -1085,7 +1094,7 @@
function twoCharLineBreak ( i )
{
return i < _input . length - 1 &&
return i < _input . length - 1 &&
( ( _input [ i ] == "\r" && _input [ i + 1 ] == "\n" )
|| ( _input [ i ] == "\n" && _input [ i + 1 ] == "\r" ) )
}
@ -1157,7 +1166,8 @@
@@ -1157,7 +1166,8 @@
meta : {
lines : _lineNum ,
delimiter : _delimiter ,
aborted : _aborted
aborted : _aborted ,
truncated : _preview > 0 && _i < _input . length
}
} ;
}
@ -1277,6 +1287,9 @@
@@ -1277,6 +1287,9 @@
if ( typeof config . complete !== 'function' )
config . complete = DEFAULTS . complete ;
if ( typeof config . error !== 'function' )
config . error = DEFAULTS . error ;
if ( typeof config . encoding !== 'string' )
config . encoding = DEFAULTS . encoding ;