Browse Source

Distribute ES module

- Use RollupJS and Terser for bundling
- Bumped up dev dependency versions
- Bumped up Travis NodeJS version matrix
- Refactored Papa worker identification
- Refactored worker logic to use `import.meta.url` or `document.currentScript.src`
https://github.com/mholt/PapaParse/issues/748
https://github.com/mholt/PapaParse/issues/813
pull/875/head
Jordan Mele 4 years ago
parent
commit
ac281a889f
  1. 3
      .eslintrc.js
  2. 7
      .travis.yml
  3. 27
      Gruntfile.js
  4. 29
      package.json
  5. 237
      papaparse.js
  6. 12
      papaparse.min.js
  7. 1849
      papaparse.mjs
  8. 27
      rollup.config.mjs

3
.eslintrc.js

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
module.exports = {
"parserOptions": {
"ecmaVersion": 5
"ecmaVersion": 2020,
"sourceType": "module"
},
"env": {
"browser": true,

7
.travis.yml

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
language: node_js
node_js:
- "8"
- "9"
- "10"
- "11"
- "12"
- "14"
- "15"
- "16"

27
Gruntfile.js

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
module.exports = function(grunt) {
grunt.initConfig({
uglify: {
options: {
compress: {
global_defs: {
'PAPA_BROWSER_CONTEXT': true
},
dead_code: true
},
output: {
comments: 'some',
},
},
min: {
files: {
'papaparse.min.js': ['papaparse.js']
},
},
},
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('build', ['uglify']);
grunt.registerTask('default', ['uglify']);
};

29
package.json

@ -34,21 +34,26 @@ @@ -34,21 +34,26 @@
"url": "https://twitter.com/mholt6"
},
"license": "MIT",
"main": "papaparse.js",
"browser": "papaparse.min.js",
"main": "./papaparse.js",
"browser": "./papaparse.min.js",
"exports": {
"import": "./papaparse.mjs",
"require": "./papaparse.js"
},
"devDependencies": {
"chai": "^4.2.0",
"connect": "^3.3.3",
"eslint": "^4.19.1",
"grunt": "^1.0.2",
"grunt-contrib-uglify": "^3.3.0",
"mocha": "^5.2.0",
"mocha-headless-chrome": "^2.0.1",
"open": "7.0.0",
"serve-static": "^1.7.1"
"chai": "^4.3.4",
"connect": "^3.7.0",
"eslint": "^7.28.0",
"mocha": "^9.0.0",
"mocha-headless-chrome": "^3.1.0",
"open": "8.2.0",
"rollup": "^2.51.1",
"rollup-plugin-terser": "^7.0.2",
"serve-static": "^1.14.1"
},
"scripts": {
"lint": "eslint --no-ignore papaparse.js Gruntfile.js .eslintrc.js 'tests/**/*.js'",
"build": "rollup -c rollup.config.mjs",
"lint": "eslint --no-ignore papaparse.mjs .eslintrc.js 'tests/**/*.js'",
"test-browser": "node tests/test.js",
"test-mocha-headless-chrome": "node tests/test.js --mocha-headless-chrome",
"test-node": "mocha tests/node-tests.js tests/test-cases.js",

237
papaparse.js

@ -1,36 +1,15 @@ @@ -1,36 +1,15 @@
/* @license
Papa Parse
v5.3.1
https://github.com/mholt/PapaParse
License: MIT
*/
(function(root, factory)
{
/* globals define */
if (typeof define === 'function' && define.amd)
{
// AMD. Register as an anonymous module.
define([], factory);
}
else if (typeof module === 'object' && typeof exports !== 'undefined')
{
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
}
else
{
// Browser globals (root is window)
root.Papa = factory();
}
// in strict mode we cannot access arguments.callee, so we need a named reference to
// stringify the factory method for the blob worker
// eslint-disable-next-line func-name
}(this, function moduleFactory()
{
'use strict';
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Papa = {}));
}(this, (function (exports) { 'use strict';
/* @license
Papa Parse
v5.3.1
https://github.com/mholt/PapaParse
License: MIT
*/
var global = (function() {
// alternative method, similar to `Function('return this')()`
@ -45,44 +24,48 @@ License: MIT @@ -45,44 +24,48 @@ License: MIT
return {};
})();
function getWorkerBlob() {
var URL = global.URL || global.webkitURL || null;
var code = moduleFactory.toString();
return Papa.BLOB_URL || (Papa.BLOB_URL = URL.createObjectURL(new Blob(['(', code, ')();'], {type: 'text/javascript'})));
}
var IS_WORKER = !global.document && !!global.postMessage,
IS_PAPA_WORKER = IS_WORKER && /blob:/i.test((global.location || {}).protocol);
var workers = {}, workerIdCounter = 0;
const PAPA_WORKER_NAME = 'papa-worker';
let WORKER_ID;
const SCRIPT_URL = global && global.document && global.document.currentScript && global.document.currentScript.src;
var IS_WORKER = !global.document && !!global.postMessage,
IS_PAPA_WORKER = IS_WORKER && global.name === PAPA_WORKER_NAME;
var Papa = {};
Papa.parse = CsvToJson;
Papa.unparse = JsonToCsv;
const parse = CsvToJson;
const unparse = JsonToCsv;
Papa.RECORD_SEP = String.fromCharCode(30);
Papa.UNIT_SEP = String.fromCharCode(31);
Papa.BYTE_ORDER_MARK = '\ufeff';
Papa.BAD_DELIMITERS = ['\r', '\n', '"', Papa.BYTE_ORDER_MARK];
Papa.WORKERS_SUPPORTED = !IS_WORKER && !!global.Worker;
Papa.NODE_STREAM_INPUT = 1;
const RECORD_SEP = String.fromCharCode(30);
const UNIT_SEP = String.fromCharCode(31);
const BYTE_ORDER_MARK = '\ufeff';
const BAD_DELIMITERS = ['\r', '\n', '"', BYTE_ORDER_MARK];
const WORKERS_SUPPORTED = !IS_WORKER && !!global.Worker && SCRIPT_URL;
const NODE_STREAM_INPUT = 1;
// Configurable chunk sizes for local and remote files, respectively
Papa.LocalChunkSize = 1024 * 1024 * 10; // 10 MB
Papa.RemoteChunkSize = 1024 * 1024 * 5; // 5 MB
Papa.DefaultDelimiter = ','; // Used if not specified and detection fails
// eslint-disable-next-line prefer-const
let LocalChunkSize = 1024 * 1024 * 10; // 10 MB
// eslint-disable-next-line prefer-const
let RemoteChunkSize = 1024 * 1024 * 5; // 5 MB
// eslint-disable-next-line prefer-const
let DefaultDelimiter = ','; // Used if not specified and detection fails
// Exposed for testing and development only
Papa.Parser = Parser;
Papa.ParserHandle = ParserHandle;
Papa.NetworkStreamer = NetworkStreamer;
Papa.FileStreamer = FileStreamer;
Papa.StringStreamer = StringStreamer;
Papa.ReadableStreamStreamer = ReadableStreamStreamer;
if (typeof PAPA_BROWSER_CONTEXT === 'undefined') {
Papa.DuplexStreamStreamer = DuplexStreamStreamer;
}
/** @private */
const Parser = _Parser;
/** @private */
const ParserHandle = _ParserHandle;
/** @private */
const NetworkStreamer = _NetworkStreamer;
/** @private */
const FileStreamer = _FileStreamer;
/** @private */
const StringStreamer = _StringStreamer;
/** @private */
const ReadableStreamStreamer = _ReadableStreamStreamer;
/** @private */
const DuplexStreamStreamer = typeof PAPA_BROWSER_CONTEXT === 'undefined'
? _DuplexStreamStreamer
: undefined;
if (global.jQuery)
{
@ -161,7 +144,7 @@ License: MIT @@ -161,7 +144,7 @@ License: MIT
fileComplete();
};
Papa.parse(f.file, f.instanceConfig);
parse(f.file, f.instanceConfig);
}
function error(name, file, elem, reason)
@ -200,7 +183,7 @@ License: MIT @@ -200,7 +183,7 @@ License: MIT
_config.transform = isFunction(_config.transform) ? _config.transform : false;
if (_config.worker && Papa.WORKERS_SUPPORTED)
if (_config.worker && WORKERS_SUPPORTED)
{
var w = newWorker();
@ -225,26 +208,26 @@ License: MIT @@ -225,26 +208,26 @@ License: MIT
}
var streamer = null;
if (_input === Papa.NODE_STREAM_INPUT && typeof PAPA_BROWSER_CONTEXT === 'undefined')
if (_input === NODE_STREAM_INPUT && typeof PAPA_BROWSER_CONTEXT === 'undefined')
{
// create a node Duplex stream for use
// with .pipe
streamer = new DuplexStreamStreamer(_config);
streamer = new _DuplexStreamStreamer(_config);
return streamer.getStream();
}
else if (typeof _input === 'string')
{
if (_config.download)
streamer = new NetworkStreamer(_config);
streamer = new _NetworkStreamer(_config);
else
streamer = new StringStreamer(_config);
streamer = new _StringStreamer(_config);
}
else if (_input.readable === true && isFunction(_input.read) && isFunction(_input.on))
{
streamer = new ReadableStreamStreamer(_config);
streamer = new _ReadableStreamStreamer(_config);
}
else if ((global.File && _input instanceof File) || _input instanceof Object) // ...Safari. (see issue #106)
streamer = new FileStreamer(_config);
streamer = new _FileStreamer(_config);
return streamer.stream(_input);
}
@ -333,7 +316,7 @@ License: MIT @@ -333,7 +316,7 @@ License: MIT
return;
if (typeof _config.delimiter === 'string'
&& !Papa.BAD_DELIMITERS.filter(function(value) { return _config.delimiter.indexOf(value) !== -1; }).length)
&& !BAD_DELIMITERS.filter(function(value) { return _config.delimiter.indexOf(value) !== -1; }).length)
{
_delimiter = _config.delimiter;
}
@ -453,7 +436,7 @@ License: MIT @@ -453,7 +436,7 @@ License: MIT
var needsQuotes = (typeof _quotes === 'boolean' && _quotes)
|| (typeof _quotes === 'function' && _quotes(str, col))
|| (Array.isArray(_quotes) && _quotes[col])
|| hasAny(escapedQuoteStr, Papa.BAD_DELIMITERS)
|| hasAny(escapedQuoteStr, BAD_DELIMITERS)
|| escapedQuoteStr.indexOf(_delimiter) > -1
|| escapedQuoteStr.charAt(0) === ' '
|| escapedQuoteStr.charAt(escapedQuoteStr.length - 1) === ' ';
@ -531,7 +514,7 @@ License: MIT @@ -531,7 +514,7 @@ License: MIT
{
global.postMessage({
results: results,
workerId: Papa.WORKER_ID,
workerId: WORKER_ID,
finished: finishedIncludingPreview
});
}
@ -570,7 +553,7 @@ License: MIT @@ -570,7 +553,7 @@ License: MIT
else if (IS_PAPA_WORKER && this._config.error)
{
global.postMessage({
workerId: Papa.WORKER_ID,
workerId: WORKER_ID,
error: error,
finished: false
});
@ -584,18 +567,18 @@ License: MIT @@ -584,18 +567,18 @@ License: MIT
configCopy.chunkSize = parseInt(configCopy.chunkSize); // parseInt VERY important so we don't concatenate strings!
if (!config.step && !config.chunk)
configCopy.chunkSize = null; // disable Range header if not streaming; bad values break IIS - see issue #196
this._handle = new ParserHandle(configCopy);
this._handle = new _ParserHandle(configCopy);
this._handle.streamer = this;
this._config = configCopy; // persist the copy to the caller
}
}
function NetworkStreamer(config)
function _NetworkStreamer(config)
{
config = config || {};
if (!config.chunkSize)
config.chunkSize = Papa.RemoteChunkSize;
config.chunkSize = RemoteChunkSize;
ChunkStreamer.call(this, config);
var xhr;
@ -704,15 +687,15 @@ License: MIT @@ -704,15 +687,15 @@ License: MIT
return parseInt(contentRange.substring(contentRange.lastIndexOf('/') + 1));
}
}
NetworkStreamer.prototype = Object.create(ChunkStreamer.prototype);
NetworkStreamer.prototype.constructor = NetworkStreamer;
_NetworkStreamer.prototype = Object.create(ChunkStreamer.prototype);
_NetworkStreamer.prototype.constructor = _NetworkStreamer;
function FileStreamer(config)
function _FileStreamer(config)
{
config = config || {};
if (!config.chunkSize)
config.chunkSize = Papa.LocalChunkSize;
config.chunkSize = LocalChunkSize;
ChunkStreamer.call(this, config);
var reader, slice;
@ -771,11 +754,11 @@ License: MIT @@ -771,11 +754,11 @@ License: MIT
};
}
FileStreamer.prototype = Object.create(ChunkStreamer.prototype);
FileStreamer.prototype.constructor = FileStreamer;
_FileStreamer.prototype = Object.create(ChunkStreamer.prototype);
_FileStreamer.prototype.constructor = _FileStreamer;
function StringStreamer(config)
function _StringStreamer(config)
{
config = config || {};
ChunkStreamer.call(this, config);
@ -802,11 +785,11 @@ License: MIT @@ -802,11 +785,11 @@ License: MIT
return this.parseChunk(chunk);
};
}
StringStreamer.prototype = Object.create(StringStreamer.prototype);
StringStreamer.prototype.constructor = StringStreamer;
_StringStreamer.prototype = Object.create(_StringStreamer.prototype);
_StringStreamer.prototype.constructor = _StringStreamer;
function ReadableStreamStreamer(config)
function _ReadableStreamStreamer(config)
{
config = config || {};
@ -896,11 +879,11 @@ License: MIT @@ -896,11 +879,11 @@ License: MIT
this._input.removeListener('error', this._streamError);
}, this);
}
ReadableStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
ReadableStreamStreamer.prototype.constructor = ReadableStreamStreamer;
_ReadableStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
_ReadableStreamStreamer.prototype.constructor = _ReadableStreamStreamer;
function DuplexStreamStreamer(_config) {
function _DuplexStreamStreamer(_config) {
var Duplex = require('stream').Duplex;
var config = copy(_config);
var parseOnWrite = true;
@ -996,13 +979,13 @@ License: MIT @@ -996,13 +979,13 @@ License: MIT
stream.once('finish', bindFunction(this._onWriteComplete, this));
}
if (typeof PAPA_BROWSER_CONTEXT === 'undefined') {
DuplexStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
DuplexStreamStreamer.prototype.constructor = DuplexStreamStreamer;
_DuplexStreamStreamer.prototype = Object.create(ChunkStreamer.prototype);
_DuplexStreamStreamer.prototype.constructor = _DuplexStreamStreamer;
}
// Use one ParserHandle per entire CSV file or string
function ParserHandle(_config)
function _ParserHandle(_config)
{
// One goal is to minimize the use of regular expressions...
var MAX_FLOAT = Math.pow(2, 53);
@ -1072,7 +1055,7 @@ License: MIT @@ -1072,7 +1055,7 @@ License: MIT
else
{
_delimiterError = true; // add error after parsing (otherwise it would be overwritten)
_config.delimiter = Papa.DefaultDelimiter;
_config.delimiter = DefaultDelimiter;
}
_results.meta.delimiter = _config.delimiter;
}
@ -1087,7 +1070,7 @@ License: MIT @@ -1087,7 +1070,7 @@ License: MIT
parserConfig.preview++; // to compensate for header row
_input = input;
_parser = new Parser(parserConfig);
_parser = new _Parser(parserConfig);
_results = _parser.parse(_input, baseIndex, ignoreLastRow);
processResults();
return _paused ? { meta: { paused: true } } : (_results || { meta: { paused: false } });
@ -1153,7 +1136,7 @@ License: MIT @@ -1153,7 +1136,7 @@ License: MIT
{
if (_results && _delimiterError)
{
addError('Delimiter', 'UndetectableDelimiter', 'Unable to auto-detect delimiting character; defaulted to \'' + Papa.DefaultDelimiter + '\'');
addError('Delimiter', 'UndetectableDelimiter', 'Unable to auto-detect delimiting character; defaulted to \'' + DefaultDelimiter + '\'');
_delimiterError = false;
}
@ -1290,14 +1273,14 @@ License: MIT @@ -1290,14 +1273,14 @@ License: MIT
function guessDelimiter(input, newline, skipEmptyLines, comments, delimitersToGuess) {
var bestDelim, bestDelta, fieldCountPrevRow, maxFieldCount;
delimitersToGuess = delimitersToGuess || [',', '\t', '|', ';', Papa.RECORD_SEP, Papa.UNIT_SEP];
delimitersToGuess = delimitersToGuess || [',', '\t', '|', ';', RECORD_SEP, UNIT_SEP];
for (var i = 0; i < delimitersToGuess.length; i++) {
var delim = delimitersToGuess[i];
var delta = 0, avgFieldCount = 0, emptyLinesCount = 0;
fieldCountPrevRow = undefined;
var preview = new Parser({
var preview = new _Parser({
comments: comments,
delimiter: delim,
newline: newline,
@ -1388,7 +1371,7 @@ License: MIT @@ -1388,7 +1371,7 @@ License: MIT
}
/** The core parser implements speedy and correct CSV parsing */
function Parser(config)
function _Parser(config)
{
// Unpack the config object
config = config || {};
@ -1412,7 +1395,7 @@ License: MIT @@ -1412,7 +1395,7 @@ License: MIT
// Delimiter must be valid
if (typeof delim !== 'string'
|| Papa.BAD_DELIMITERS.indexOf(delim) > -1)
|| BAD_DELIMITERS.indexOf(delim) > -1)
delim = ',';
// Comment character must be valid
@ -1421,7 +1404,7 @@ License: MIT @@ -1421,7 +1404,7 @@ License: MIT
else if (comments === true)
comments = '#';
else if (typeof comments !== 'string'
|| Papa.BAD_DELIMITERS.indexOf(comments) > -1)
|| BAD_DELIMITERS.indexOf(comments) > -1)
comments = false;
// Newline must be valid: \r, \n, or \r\n
@ -1665,9 +1648,9 @@ License: MIT @@ -1665,9 +1648,9 @@ License: MIT
}
/**
* checks if there are extra spaces after closing quote and given index without any text
* if Yes, returns the number of spaces
*/
* checks if there are extra spaces after closing quote and given index without any text
* if Yes, returns the number of spaces
*/
function extraSpaces(index) {
var spaceLength = 0;
if (index !== -1) {
@ -1752,11 +1735,11 @@ License: MIT @@ -1752,11 +1735,11 @@ License: MIT
function newWorker()
{
if (!Papa.WORKERS_SUPPORTED)
if (!WORKERS_SUPPORTED)
return false;
var workerUrl = getWorkerBlob();
var w = new global.Worker(workerUrl);
var workerUrl = SCRIPT_URL;
var w = new global.Worker(workerUrl, { name: PAPA_WORKER_NAME });
w.onmessage = mainThreadReceivedMessage;
w.id = workerIdCounter++;
workers[w.id] = w;
@ -1827,23 +1810,23 @@ License: MIT @@ -1827,23 +1810,23 @@ License: MIT
{
var msg = e.data;
if (typeof Papa.WORKER_ID === 'undefined' && msg)
Papa.WORKER_ID = msg.workerId;
if (typeof WORKER_ID === 'undefined' && msg)
WORKER_ID = msg.workerId;
if (typeof msg.input === 'string')
{
global.postMessage({
workerId: Papa.WORKER_ID,
results: Papa.parse(msg.input, msg.config),
workerId: WORKER_ID,
results: parse(msg.input, msg.config),
finished: true
});
}
else if ((global.File && msg.input instanceof File) || msg.input instanceof Object) // thank you, Safari (see issue #106)
{
var results = Papa.parse(msg.input, msg.config);
var results = parse(msg.input, msg.config);
if (results)
global.postMessage({
workerId: Papa.WORKER_ID,
workerId: WORKER_ID,
results: results,
finished: true
});
@ -1871,5 +1854,25 @@ License: MIT @@ -1871,5 +1854,25 @@ License: MIT
return typeof func === 'function';
}
return Papa;
}));
exports.BAD_DELIMITERS = BAD_DELIMITERS;
exports.BYTE_ORDER_MARK = BYTE_ORDER_MARK;
exports.DefaultDelimiter = DefaultDelimiter;
exports.DuplexStreamStreamer = DuplexStreamStreamer;
exports.FileStreamer = FileStreamer;
exports.LocalChunkSize = LocalChunkSize;
exports.NODE_STREAM_INPUT = NODE_STREAM_INPUT;
exports.NetworkStreamer = NetworkStreamer;
exports.Parser = Parser;
exports.ParserHandle = ParserHandle;
exports.RECORD_SEP = RECORD_SEP;
exports.ReadableStreamStreamer = ReadableStreamStreamer;
exports.RemoteChunkSize = RemoteChunkSize;
exports.StringStreamer = StringStreamer;
exports.UNIT_SEP = UNIT_SEP;
exports.WORKERS_SUPPORTED = WORKERS_SUPPORTED;
exports.parse = parse;
exports.unparse = unparse;
Object.defineProperty(exports, '__esModule', { value: true });
})));

12
papaparse.min.js vendored

File diff suppressed because one or more lines are too long

1849
papaparse.mjs

File diff suppressed because it is too large Load Diff

27
rollup.config.mjs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
import { terser } from "rollup-plugin-terser";
export default {
input: 'papaparse.mjs',
output: [
{
name: 'Papa',
file: 'papaparse.js',
format: 'umd'
},
{
name: 'Papa',
file: 'papaparse.min.js',
format: 'umd',
plugins: [terser()]
}
],
plugins: [
{
resolveImportMeta(prop, { format }) {
if (prop === 'url' && format === 'umd') {
return 'global && global.document && global.document.currentScript && global.document.currentScript.src';
}
}
}
]
};
Loading…
Cancel
Save