diff --git a/node_modules/async/LICENSE b/node_modules/async/LICENSE
index b7f9d500..8f296985 100644
--- a/node_modules/async/LICENSE
+++ b/node_modules/async/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010 Caolan McMahon
+Copyright (c) 2010-2014 Caolan McMahon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/node_modules/async/index.js b/node_modules/async/index.js
deleted file mode 100644
index 8e238453..00000000
--- a/node_modules/async/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-// This file is just added for convenience so this repository can be
-// directly checked out into a project's deps folder
-module.exports = require('./lib/async');
diff --git a/node_modules/async/lib/async.js b/node_modules/async/lib/async.js
old mode 100644
new mode 100755
index 7cc4f5ea..01e8afcc
--- a/node_modules/async/lib/async.js
+++ b/node_modules/async/lib/async.js
@@ -1,17 +1,22 @@
-/*global setTimeout: false, console: false */
+/*!
+ * async
+ * https://github.com/caolan/async
+ *
+ * Copyright 2010-2014 Caolan McMahon
+ * Released under the MIT license
+ */
+/*jshint onevar: false, indent:4 */
+/*global setImmediate: false, setTimeout: false, console: false */
(function () {
var async = {};
// global on the server, window in the browser
- var root = this,
- previous_async = root.async;
+ var root, previous_async;
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = async;
- }
- else {
- root.async = async;
+ root = this;
+ if (root != null) {
+ previous_async = root.async;
}
async.noConflict = function () {
@@ -19,9 +24,24 @@
return async;
};
+ function only_once(fn) {
+ var called = false;
+ return function() {
+ if (called) throw new Error("Callback was already called.");
+ called = true;
+ fn.apply(root, arguments);
+ }
+ }
+
//// cross-browser compatiblity functions ////
- var _forEach = function (arr, iterator) {
+ var _toString = Object.prototype.toString;
+
+ var _isArray = Array.isArray || function (obj) {
+ return _toString.call(obj) === '[object Array]';
+ };
+
+ var _each = function (arr, iterator) {
if (arr.forEach) {
return arr.forEach(iterator);
}
@@ -35,7 +55,7 @@
return arr.map(iterator);
}
var results = [];
- _forEach(arr, function (x, i, a) {
+ _each(arr, function (x, i, a) {
results.push(iterator(x, i, a));
});
return results;
@@ -45,7 +65,7 @@
if (arr.reduce) {
return arr.reduce(iterator, memo);
}
- _forEach(arr, function (x, i, a) {
+ _each(arr, function (x, i, a) {
memo = iterator(memo, x, i, a);
});
return memo;
@@ -68,37 +88,58 @@
//// nextTick implementation with browser-compatible fallback ////
if (typeof process === 'undefined' || !(process.nextTick)) {
- async.nextTick = function (fn) {
- setTimeout(fn, 0);
- };
+ if (typeof setImmediate === 'function') {
+ async.nextTick = function (fn) {
+ // not a direct alias for IE10 compatibility
+ setImmediate(fn);
+ };
+ async.setImmediate = async.nextTick;
+ }
+ else {
+ async.nextTick = function (fn) {
+ setTimeout(fn, 0);
+ };
+ async.setImmediate = async.nextTick;
+ }
}
else {
async.nextTick = process.nextTick;
+ if (typeof setImmediate !== 'undefined') {
+ async.setImmediate = function (fn) {
+ // not a direct alias for IE10 compatibility
+ setImmediate(fn);
+ };
+ }
+ else {
+ async.setImmediate = async.nextTick;
+ }
}
- async.forEach = function (arr, iterator, callback) {
+ async.each = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0;
- _forEach(arr, function (x) {
- iterator(x, function (err) {
- if (err) {
- callback(err);
- callback = function () {};
- }
- else {
- completed += 1;
- if (completed === arr.length) {
- callback(null);
- }
- }
- });
+ _each(arr, function (x) {
+ iterator(x, only_once(done) );
});
+ function done(err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ if (completed >= arr.length) {
+ callback();
+ }
+ }
+ }
};
+ async.forEach = async.each;
- async.forEachSeries = function (arr, iterator, callback) {
+ async.eachSeries = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
@@ -112,8 +153,8 @@
}
else {
completed += 1;
- if (completed === arr.length) {
- callback(null);
+ if (completed >= arr.length) {
+ callback();
}
else {
iterate();
@@ -123,81 +164,111 @@
};
iterate();
};
+ async.forEachSeries = async.eachSeries;
- async.forEachLimit = function (arr, limit, iterator, callback) {
- callback = callback || function () {};
- if (!arr.length || limit <= 0) {
- return callback();
- }
- var completed = 0;
- var started = 0;
- var running = 0;
+ async.eachLimit = function (arr, limit, iterator, callback) {
+ var fn = _eachLimit(limit);
+ fn.apply(null, [arr, iterator, callback]);
+ };
+ async.forEachLimit = async.eachLimit;
- (function replenish () {
- if (completed === arr.length) {
+ var _eachLimit = function (limit) {
+
+ return function (arr, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length || limit <= 0) {
return callback();
}
+ var completed = 0;
+ var started = 0;
+ var running = 0;
- while (running < limit && started < arr.length) {
- started += 1;
- running += 1;
- iterator(arr[started - 1], function (err) {
- if (err) {
- callback(err);
- callback = function () {};
- }
- else {
- completed += 1;
- running -= 1;
- if (completed === arr.length) {
- callback();
+ (function replenish () {
+ if (completed >= arr.length) {
+ return callback();
+ }
+
+ while (running < limit && started < arr.length) {
+ started += 1;
+ running += 1;
+ iterator(arr[started - 1], function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
}
else {
- replenish();
+ completed += 1;
+ running -= 1;
+ if (completed >= arr.length) {
+ callback();
+ }
+ else {
+ replenish();
+ }
}
- }
- });
- }
- })();
+ });
+ }
+ })();
+ };
};
var doParallel = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
- return fn.apply(null, [async.forEach].concat(args));
+ return fn.apply(null, [async.each].concat(args));
+ };
+ };
+ var doParallelLimit = function(limit, fn) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [_eachLimit(limit)].concat(args));
};
};
var doSeries = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
- return fn.apply(null, [async.forEachSeries].concat(args));
+ return fn.apply(null, [async.eachSeries].concat(args));
};
};
var _asyncMap = function (eachfn, arr, iterator, callback) {
- var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
- eachfn(arr, function (x, callback) {
- iterator(x.value, function (err, v) {
- results[x.index] = v;
- callback(err);
+ if (!callback) {
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (err) {
+ callback(err);
+ });
});
- }, function (err) {
- callback(err, results);
- });
+ } else {
+ var results = [];
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (err, v) {
+ results[x.index] = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ }
};
async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
+ async.mapLimit = function (arr, limit, iterator, callback) {
+ return _mapLimit(limit)(arr, iterator, callback);
+ };
+ var _mapLimit = function(limit) {
+ return doParallelLimit(limit, _asyncMap);
+ };
// reduce only has a series version, as doing reduce in parallel won't
// work in many situations.
async.reduce = function (arr, memo, iterator, callback) {
- async.forEachSeries(arr, function (x, callback) {
+ async.eachSeries(arr, function (x, callback) {
iterator(memo, x, function (err, v) {
memo = v;
callback(err);
@@ -288,7 +359,7 @@
async.detectSeries = doSeries(_detect);
async.some = function (arr, iterator, main_callback) {
- async.forEach(arr, function (x, callback) {
+ async.each(arr, function (x, callback) {
iterator(x, function (v) {
if (v) {
main_callback(true);
@@ -304,7 +375,7 @@
async.any = async.some;
async.every = function (arr, iterator, main_callback) {
- async.forEach(arr, function (x, callback) {
+ async.each(arr, function (x, callback) {
iterator(x, function (v) {
if (!v) {
main_callback(false);
@@ -348,8 +419,9 @@
async.auto = function (tasks, callback) {
callback = callback || function () {};
var keys = _keys(tasks);
- if (!keys.length) {
- return callback(null);
+ var remainingTasks = keys.length
+ if (!remainingTasks) {
+ return callback();
}
var results = {};
@@ -367,33 +439,42 @@
}
};
var taskComplete = function () {
- _forEach(listeners.slice(0), function (fn) {
+ remainingTasks--
+ _each(listeners.slice(0), function (fn) {
fn();
});
};
addListener(function () {
- if (_keys(results).length === keys.length) {
- callback(null, results);
+ if (!remainingTasks) {
+ var theCallback = callback;
+ // prevent final callback from calling itself if it errors
callback = function () {};
+
+ theCallback(null, results);
}
});
- _forEach(keys, function (k) {
- var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
+ _each(keys, function (k) {
+ var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
var taskCallback = function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
if (err) {
- callback(err);
+ var safeResults = {};
+ _each(_keys(results), function(rkey) {
+ safeResults[rkey] = results[rkey];
+ });
+ safeResults[k] = args;
+ callback(err, safeResults);
// stop subsequent errors hitting callback multiple times
callback = function () {};
}
else {
- var args = Array.prototype.slice.call(arguments, 1);
- if (args.length <= 1) {
- args = args[0];
- }
results[k] = args;
- taskComplete();
+ async.setImmediate(taskComplete);
}
};
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
@@ -417,15 +498,50 @@
});
};
+ async.retry = function(times, task, callback) {
+ var DEFAULT_TIMES = 5;
+ var attempts = [];
+ // Use defaults if times not passed
+ if (typeof times === 'function') {
+ callback = task;
+ task = times;
+ times = DEFAULT_TIMES;
+ }
+ // Make sure times is a number
+ times = parseInt(times, 10) || DEFAULT_TIMES;
+ var wrappedTask = function(wrappedCallback, wrappedResults) {
+ var retryAttempt = function(task, finalAttempt) {
+ return function(seriesCallback) {
+ task(function(err, result){
+ seriesCallback(!err || finalAttempt, {err: err, result: result});
+ }, wrappedResults);
+ };
+ };
+ while (times) {
+ attempts.push(retryAttempt(task, !(times-=1)));
+ }
+ async.series(attempts, function(done, data){
+ data = data[data.length - 1];
+ (wrappedCallback || callback)(data.err, data.result);
+ });
+ }
+ // If a callback is passed, run this as a controll flow
+ return callback ? wrappedTask() : wrappedTask
+ };
+
async.waterfall = function (tasks, callback) {
callback = callback || function () {};
+ if (!_isArray(tasks)) {
+ var err = new Error('First argument to waterfall must be an array of functions');
+ return callback(err);
+ }
if (!tasks.length) {
return callback();
}
var wrapIterator = function (iterator) {
return function (err) {
if (err) {
- callback(err);
+ callback.apply(null, arguments);
callback = function () {};
}
else {
@@ -437,7 +553,7 @@
else {
args.push(callback);
}
- async.nextTick(function () {
+ async.setImmediate(function () {
iterator.apply(null, args);
});
}
@@ -446,10 +562,10 @@
wrapIterator(async.iterator(tasks))();
};
- async.parallel = function (tasks, callback) {
+ var _parallel = function(eachfn, tasks, callback) {
callback = callback || function () {};
- if (tasks.constructor === Array) {
- async.map(tasks, function (fn, callback) {
+ if (_isArray(tasks)) {
+ eachfn.map(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
var args = Array.prototype.slice.call(arguments, 1);
@@ -463,7 +579,7 @@
}
else {
var results = {};
- async.forEach(_keys(tasks), function (k, callback) {
+ eachfn.each(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
@@ -478,9 +594,17 @@
}
};
+ async.parallel = function (tasks, callback) {
+ _parallel({ map: async.map, each: async.each }, tasks, callback);
+ };
+
+ async.parallelLimit = function(tasks, limit, callback) {
+ _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+ };
+
async.series = function (tasks, callback) {
callback = callback || function () {};
- if (tasks.constructor === Array) {
+ if (_isArray(tasks)) {
async.mapSeries(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
@@ -495,7 +619,7 @@
}
else {
var results = {};
- async.forEachSeries(_keys(tasks), function (k, callback) {
+ async.eachSeries(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
@@ -563,6 +687,21 @@
}
};
+ async.doWhilst = function (iterator, test, callback) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (test.apply(null, args)) {
+ async.doWhilst(iterator, test, callback);
+ }
+ else {
+ callback();
+ }
+ });
+ };
+
async.until = function (test, iterator, callback) {
if (!test()) {
iterator(function (err) {
@@ -577,7 +716,59 @@
}
};
+ async.doUntil = function (iterator, test, callback) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (!test.apply(null, args)) {
+ async.doUntil(iterator, test, callback);
+ }
+ else {
+ callback();
+ }
+ });
+ };
+
async.queue = function (worker, concurrency) {
+ if (concurrency === undefined) {
+ concurrency = 1;
+ }
+ function _insert(q, data, pos, callback) {
+ if (!q.started){
+ q.started = true;
+ }
+ if (!_isArray(data)) {
+ data = [data];
+ }
+ if(data.length == 0) {
+ // call drain immediately if there are no tasks
+ return async.setImmediate(function() {
+ if (q.drain) {
+ q.drain();
+ }
+ });
+ }
+ _each(data, function(task) {
+ var item = {
+ data: task,
+ callback: typeof callback === 'function' ? callback : null
+ };
+
+ if (pos) {
+ q.tasks.unshift(item);
+ } else {
+ q.tasks.push(item);
+ }
+
+ if (q.saturated && q.tasks.length === q.concurrency) {
+ q.saturated();
+ }
+ async.setImmediate(q.process);
+ });
+ }
+
var workers = 0;
var q = {
tasks: [],
@@ -585,34 +776,37 @@
saturated: null,
empty: null,
drain: null,
+ started: false,
+ paused: false,
push: function (data, callback) {
- if(data.constructor !== Array) {
- data = [data];
- }
- _forEach(data, function(task) {
- q.tasks.push({
- data: task,
- callback: typeof callback === 'function' ? callback : null
- });
- if (q.saturated && q.tasks.length == concurrency) {
- q.saturated();
- }
- async.nextTick(q.process);
- });
+ _insert(q, data, false, callback);
+ },
+ kill: function () {
+ q.drain = null;
+ q.tasks = [];
+ },
+ unshift: function (data, callback) {
+ _insert(q, data, true, callback);
},
process: function () {
- if (workers < q.concurrency && q.tasks.length) {
+ if (!q.paused && workers < q.concurrency && q.tasks.length) {
var task = q.tasks.shift();
- if(q.empty && q.tasks.length == 0) q.empty();
+ if (q.empty && q.tasks.length === 0) {
+ q.empty();
+ }
workers += 1;
- worker(task.data, function () {
+ var next = function () {
workers -= 1;
if (task.callback) {
task.callback.apply(task, arguments);
}
- if(q.drain && q.tasks.length + workers == 0) q.drain();
+ if (q.drain && q.tasks.length + workers === 0) {
+ q.drain();
+ }
q.process();
- });
+ };
+ var cb = only_once(next);
+ worker(task.data, cb);
}
},
length: function () {
@@ -620,10 +814,156 @@
},
running: function () {
return workers;
+ },
+ idle: function() {
+ return q.tasks.length + workers === 0;
+ },
+ pause: function () {
+ if (q.paused === true) { return; }
+ q.paused = true;
+ q.process();
+ },
+ resume: function () {
+ if (q.paused === false) { return; }
+ q.paused = false;
+ q.process();
}
};
return q;
};
+
+ async.priorityQueue = function (worker, concurrency) {
+
+ function _compareTasks(a, b){
+ return a.priority - b.priority;
+ };
+
+ function _binarySearch(sequence, item, compare) {
+ var beg = -1,
+ end = sequence.length - 1;
+ while (beg < end) {
+ var mid = beg + ((end - beg + 1) >>> 1);
+ if (compare(item, sequence[mid]) >= 0) {
+ beg = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return beg;
+ }
+
+ function _insert(q, data, priority, callback) {
+ if (!q.started){
+ q.started = true;
+ }
+ if (!_isArray(data)) {
+ data = [data];
+ }
+ if(data.length == 0) {
+ // call drain immediately if there are no tasks
+ return async.setImmediate(function() {
+ if (q.drain) {
+ q.drain();
+ }
+ });
+ }
+ _each(data, function(task) {
+ var item = {
+ data: task,
+ priority: priority,
+ callback: typeof callback === 'function' ? callback : null
+ };
+
+ q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
+
+ if (q.saturated && q.tasks.length === q.concurrency) {
+ q.saturated();
+ }
+ async.setImmediate(q.process);
+ });
+ }
+
+ // Start with a normal queue
+ var q = async.queue(worker, concurrency);
+
+ // Override push to accept second parameter representing priority
+ q.push = function (data, priority, callback) {
+ _insert(q, data, priority, callback);
+ };
+
+ // Remove unshift function
+ delete q.unshift;
+
+ return q;
+ };
+
+ async.cargo = function (worker, payload) {
+ var working = false,
+ tasks = [];
+
+ var cargo = {
+ tasks: tasks,
+ payload: payload,
+ saturated: null,
+ empty: null,
+ drain: null,
+ drained: true,
+ push: function (data, callback) {
+ if (!_isArray(data)) {
+ data = [data];
+ }
+ _each(data, function(task) {
+ tasks.push({
+ data: task,
+ callback: typeof callback === 'function' ? callback : null
+ });
+ cargo.drained = false;
+ if (cargo.saturated && tasks.length === payload) {
+ cargo.saturated();
+ }
+ });
+ async.setImmediate(cargo.process);
+ },
+ process: function process() {
+ if (working) return;
+ if (tasks.length === 0) {
+ if(cargo.drain && !cargo.drained) cargo.drain();
+ cargo.drained = true;
+ return;
+ }
+
+ var ts = typeof payload === 'number'
+ ? tasks.splice(0, payload)
+ : tasks.splice(0, tasks.length);
+
+ var ds = _map(ts, function (task) {
+ return task.data;
+ });
+
+ if(cargo.empty) cargo.empty();
+ working = true;
+ worker(ds, function () {
+ working = false;
+
+ var args = arguments;
+ _each(ts, function (data) {
+ if (data.callback) {
+ data.callback.apply(null, args);
+ }
+ });
+
+ process();
+ });
+ },
+ length: function () {
+ return tasks.length;
+ },
+ running: function () {
+ return working;
+ }
+ };
+ return cargo;
+ };
var _console_fn = function (name) {
return function (fn) {
@@ -637,7 +977,7 @@
}
}
else if (console[name]) {
- _forEach(args, function (x) {
+ _each(args, function (x) {
console[name](x);
});
}
@@ -662,7 +1002,9 @@
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
- callback.apply(null, memo[key]);
+ async.nextTick(function () {
+ callback.apply(null, memo[key]);
+ });
}
else if (key in queues) {
queues[key].push(callback);
@@ -679,6 +1021,7 @@
}]));
}
};
+ memoized.memo = memo;
memoized.unmemoized = fn;
return memoized;
};
@@ -689,4 +1032,92 @@
};
};
+ async.times = function (count, iterator, callback) {
+ var counter = [];
+ for (var i = 0; i < count; i++) {
+ counter.push(i);
+ }
+ return async.map(counter, iterator, callback);
+ };
+
+ async.timesSeries = function (count, iterator, callback) {
+ var counter = [];
+ for (var i = 0; i < count; i++) {
+ counter.push(i);
+ }
+ return async.mapSeries(counter, iterator, callback);
+ };
+
+ async.seq = function (/* functions... */) {
+ var fns = arguments;
+ return function () {
+ var that = this;
+ var args = Array.prototype.slice.call(arguments);
+ var callback = args.pop();
+ async.reduce(fns, args, function (newargs, fn, cb) {
+ fn.apply(that, newargs.concat([function () {
+ var err = arguments[0];
+ var nextargs = Array.prototype.slice.call(arguments, 1);
+ cb(err, nextargs);
+ }]))
+ },
+ function (err, results) {
+ callback.apply(that, [err].concat(results));
+ });
+ };
+ };
+
+ async.compose = function (/* functions... */) {
+ return async.seq.apply(null, Array.prototype.reverse.call(arguments));
+ };
+
+ var _applyEach = function (eachfn, fns /*args...*/) {
+ var go = function () {
+ var that = this;
+ var args = Array.prototype.slice.call(arguments);
+ var callback = args.pop();
+ return eachfn(fns, function (fn, cb) {
+ fn.apply(that, args.concat([cb]));
+ },
+ callback);
+ };
+ if (arguments.length > 2) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ return go.apply(this, args);
+ }
+ else {
+ return go;
+ }
+ };
+ async.applyEach = doParallel(_applyEach);
+ async.applyEachSeries = doSeries(_applyEach);
+
+ async.forever = function (fn, callback) {
+ function next(err) {
+ if (err) {
+ if (callback) {
+ return callback(err);
+ }
+ throw err;
+ }
+ fn(next);
+ }
+ next();
+ };
+
+ // Node.js
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = async;
+ }
+ // AMD / RequireJS
+ else if (typeof define !== 'undefined' && define.amd) {
+ define([], function () {
+ return async;
+ });
+ }
+ // included directly via \n \n\n\n## Documentation\n\n### Collections\n\n* [forEach](#forEach)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [until](#until)\n* [waterfall](#waterfall)\n* [queue](#queue)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n### forEach(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the forEach function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // assuming openFiles is an array of file names and saveFile is a function\n // to save the modified contents of that file:\n\n async.forEach(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n\n---------------------------------------\n\n\n### forEachSeries(arr, iterator, callback)\n\nThe same as forEach only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n### forEachLimit(arr, limit, iterator, callback)\n\nThe same as forEach only the iterator is applied to batches of items in the\narray, in series. The next batch of iterators is only called once the current\none has completed processing.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - How many items should be in each batch.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // Assume documents is an array of JSON objects and requestApi is a\n // function that interacts with a rate-limited REST api.\n\n async.forEachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as filter, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then its probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback which accepts an optional error as its first argument, and the state\n of the reduction as the second. If an error is passed to the callback, the\n reduction is stopped and the main callback is immediately called with the\n error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n async.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n }, function(err, result){\n // result is now equal to the last value of memo, which is 6\n });\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n async.detect(['file1','file2','file3'], path.exists, function(result){\n // result now equals the first file in the list that exists\n });\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a value to use as the sort criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n async.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n }, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n });\n\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n async.some(['file1','file2','file3'], path.exists, function(result){\n // if result is true then at least one of the files exists\n });\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n async.every(['file1','file2','file3'], path.exists, function(result){\n // if result is true then every file exists\n });\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n });\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n },\n ],\n // optional callback\n function(err, results){\n // results is now equal to ['one', 'two']\n });\n\n\n // an example using an object instead of an array\n async.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equal to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed a\n callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n },\n ],\n // optional callback\n function(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n });\n\n\n // an example using an object instead of an array\n async.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equals to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback which must be called once it has completed with an optional\n error as the first argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n var count = 0;\n\n async.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n );\n\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n async.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n ], function (err, result) {\n // result now equals 'done' \n });\n\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n // create a queue object with concurrency 2\n\n var q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n }, 2);\n\n\n // assign a callback\n q.drain = function() {\n console.log('all items have been processed');\n }\n\n // add some items to the queue\n\n q.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n });\n q.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n });\n\n // add some items to the queue (batch-wise)\n\n q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n });\n\n\n---------------------------------------\n\n\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The\n syntax is easier to understand by looking at the example.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. If all tasks complete\n successfully, it will receive an object containing their results.\n\n__Example__\n\n async.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n });\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n async.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n ],\n function(results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n email_link: function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n });\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. Its also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n\n__Example__\n\n var iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n ]);\n\n node> var iterator2 = iterator();\n 'one'\n node> var iterator3 = iterator2();\n 'two'\n node> iterator3();\n 'three'\n node> var nextfn = iterator2.next();\n node> nextfn();\n 'three'\n\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n // using apply\n\n async.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n ]);\n\n\n // the same process without using apply\n\n async.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n },\n ]);\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n node> var fn = async.apply(sys.puts, 'one');\n node> fn('two', 'three');\n one\n two\n three\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setTimeout(callback, 0),\nwhich means other higher priority events may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n var call_order = [];\n async.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two]\n });\n call_order.push('one')\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n var slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n };\n var fn = async.memoize(slow_fn);\n\n // fn can now be used as if it were slow_fn\n fn('some name', function () {\n // callback\n });\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n };\n\n node> async.log(hello, 'world');\n 'hello world'\n\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n };\n\n node> async.dir(hello, 'world');\n {hello: 'world'}\n\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n",
+ "jam": {
+ "main": "lib/async.js",
+ "include": [
+ "lib/async.js",
+ "README.md",
+ "LICENSE"
+ ]
+ },
+ "scripts": {
+ "test": "nodeunit test/test-async.js"
+ },
+ "readme": "# Async.js\n\n[](https://travis-ci.org/caolan/async)\n\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [Node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns\nfor asynchronous control flow (`parallel`, `series`, `waterfall`…). All these\nfunctions assume you follow the Node.js convention of providing a single\ncallback as the last argument of your `async` function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n\nasync.parallel([\n function(){ ... },\n function(){ ... }\n], callback);\n\nasync.series([\n function(){ ... },\n function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about `bind`, not about `async`. If you are wondering how to\nmake `async` execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n squareExponent: 2,\n square: function(number, callback){ \n var result = Math.pow(number, this.squareExponent);\n setTimeout(function(){\n callback(null, result);\n }, 200);\n }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n // result is [NaN, NaN, NaN]\n // This fails because the `this.squareExponent` expression in the square\n // function is not evaluated in the context of AsyncSquaringLibrary, and is\n // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n // result is [1, 4, 9]\n // With the help of bind we can attach a context to the iterator before\n // passing it to async. Now the square function will be executed in its \n // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (`npm`):\n\n npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. \n\nUsage:\n\n```html\n\n\n```\n\n## Documentation\n\n### Collections\n\n* [`each`](#each)\n* [`eachSeries`](#eachSeries)\n* [`eachLimit`](#eachLimit)\n* [`map`](#map)\n* [`mapSeries`](#mapSeries)\n* [`mapLimit`](#mapLimit)\n* [`filter`](#filter)\n* [`filterSeries`](#filterSeries)\n* [`reject`](#reject)\n* [`rejectSeries`](#rejectSeries)\n* [`reduce`](#reduce)\n* [`reduceRight`](#reduceRight)\n* [`detect`](#detect)\n* [`detectSeries`](#detectSeries)\n* [`sortBy`](#sortBy)\n* [`some`](#some)\n* [`every`](#every)\n* [`concat`](#concat)\n* [`concatSeries`](#concatSeries)\n\n### Control Flow\n\n* [`series`](#seriestasks-callback)\n* [`parallel`](#parallel)\n* [`parallelLimit`](#parallellimittasks-limit-callback)\n* [`whilst`](#whilst)\n* [`doWhilst`](#doWhilst)\n* [`until`](#until)\n* [`doUntil`](#doUntil)\n* [`forever`](#forever)\n* [`waterfall`](#waterfall)\n* [`compose`](#compose)\n* [`seq`](#seq)\n* [`applyEach`](#applyEach)\n* [`applyEachSeries`](#applyEachSeries)\n* [`queue`](#queue)\n* [`priorityQueue`](#priorityQueue)\n* [`cargo`](#cargo)\n* [`auto`](#auto)\n* [`retry`](#retry)\n* [`iterator`](#iterator)\n* [`apply`](#apply)\n* [`nextTick`](#nextTick)\n* [`times`](#times)\n* [`timesSeries`](#timesSeries)\n\n### Utils\n\n* [`memoize`](#memoize)\n* [`unmemoize`](#unmemoize)\n* [`log`](#log)\n* [`dir`](#dir)\n* [`noConflict`](#noConflict)\n\n\n## Collections\n\n\n\n### each(arr, iterator, callback)\n\nApplies the function `iterator` to each item in `arr`, in parallel.\nThe `iterator` is called with an item from the list, and a callback for when it\nhas finished. If the `iterator` passes an error to its `callback`, the main\n`callback` (for the `each` function) is immediately called with the error.\n\nNote, that since this function applies `iterator` to each item in parallel,\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err)` which must be called once it has \n completed. If no error has occured, the `callback` should be run without \n arguments or with an explicit `null` argument.\n* `callback(err)` - A callback which is called when all `iterator` functions\n have finished, or an error occurs.\n\n__Examples__\n\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n```js\n// assuming openFiles is an array of file names \n\nasync.each(openFiles, function( file, callback) {\n \n // Perform operation on file here.\n console.log('Processing file ' + file);\n \n if( file.length > 32 ) {\n console.log('This file name is too long');\n callback('File name too long');\n } else {\n // Do work to process file here\n console.log('File processed');\n callback();\n }\n}, function(err){\n // if any of the file processing produced an error, err would equal that error\n if( err ) {\n // One of the iterations produced an error.\n // All processing will now stop.\n console.log('A file failed to process');\n } else {\n console.log('All files have been processed successfully');\n }\n});\n```\n\n---------------------------------------\n\n\n\n### eachSeries(arr, iterator, callback)\n\nThe same as [`each`](#each), only `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThis means the `iterator` functions will complete in order.\n\n\n---------------------------------------\n\n\n\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items in `arr` are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err)` which must be called once it has \n completed. If no error has occured, the callback should be run without \n arguments or with an explicit `null` argument.\n* `callback(err)` - A callback which is called when all `iterator` functions\n have finished, or an error occurs.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in `arr` through\nthe `iterator` function. The `iterator` is called with an item from `arr` and a\ncallback for when it has finished processing. Each of these callback takes 2 arguments: \nan `error`, and the transformed item from `arr`. If `iterator` passes an error to this \ncallback, the main `callback` (for the `map` function) is immediately called with the error.\n\nNote, that since this function applies the `iterator` to each item in parallel,\nthere is no guarantee that the `iterator` functions will complete in order. \nHowever, the results array will be in the same order as the original `arr`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, transformed)` which must be called once \n it has completed with an error (which can be `null`) and a transformed item.\n* `callback(err, results)` - A callback which is called when all `iterator`\n functions have finished, or an error occurs. Results is an array of the\n transformed items from the `arr`.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as [`map`](#map), only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that \nthe first `limit` `iterator` functions will complete before any others are started.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `limit` - The maximum number of `iterator`s to run at any time.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, transformed)` which must be called once \n it has completed with an error (which can be `null`) and a transformed item.\n* `callback(err, results)` - A callback which is called when all `iterator`\n calls have finished, or an error occurs. The result is an array of the\n transformed items from the original `arr`.\n\n__Example__\n\n```js\nasync.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){\n // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ `select`\n\nReturns a new array of all the values in `arr` which pass an async truth test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in `arr`.\n The `iterator` is passed a `callback(truthValue)`, which must be called with a \n boolean argument once it has completed.\n* `callback(results)` - A callback which is called after all the `iterator`\n functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n\n\n### filterSeries(arr, iterator, callback)\n\n__Alias:__ `selectSeries`\n\nThe same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of [`filter`](#filter). Removes values that pass an `async` truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__Aliases:__ `inject`, `foldl`\n\nReduces `arr` into a single value using an async `iterator` to return\neach successive step. `memo` is the initial state of the reduction. \nThis function only operates in series. \n\nFor performance reasons, it may make sense to split a call to this function into \na parallel map, and then use the normal `Array.prototype.reduce` on the results. \nThis function is for situations where each step in the reduction needs to be async; \nif you can get the data before reducing it, then it's probably a good idea to do so.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `memo` - The initial state of the reduction.\n* `iterator(memo, item, callback)` - A function applied to each item in the\n array to produce the next step in the reduction. The `iterator` is passed a\n `callback(err, reduction)` which accepts an optional error as its first \n argument, and the state of the reduction as the second. If an error is \n passed to the callback, the reduction is stopped and the main `callback` is \n immediately called with the error.\n* `callback(err, result)` - A callback which is called after all the `iterator`\n functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n}, function(err, result){\n // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ `foldr`\n\nSame as [`reduce`](#reduce), only operates on `arr` in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in `arr` that passes an async truth test. The\n`iterator` is applied in parallel, meaning the first iterator to return `true` will\nfire the detect `callback` with that result. That means the result might not be\nthe first item in the original `arr` (in terms of order) that passes the test.\n\nIf order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in `arr`.\n The iterator is passed a `callback(truthValue)` which must be called with a \n boolean argument once it has completed.\n* `callback(result)` - A callback which is called as soon as any iterator returns\n `true`, or after all the `iterator` functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value `undefined` if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`\nin series. This means the result is always the first in the original `arr` (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each `arr` value through an async `iterator`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, sortValue)` which must be called once it\n has completed with an error (which can be `null`) and a value to use as the sort\n criteria.\n* `callback(err, results)` - A callback which is called after all the `iterator`\n functions have finished, or an error occurs. Results is the items from\n the original `arr` sorted by the values returned by the `iterator` calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n}, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n});\n```\n\n__Sort Order__\n\nBy modifying the callback parameter the sorting order can be influenced:\n\n```js\n//ascending order\nasync.sortBy([1,9,3,5], function(x, callback){\n callback(err, x);\n}, function(err,result){\n //result callback\n} );\n\n//descending order\nasync.sortBy([1,9,3,5], function(x, callback){\n callback(err, x*-1); //<- x*-1 instead of x, turns the order around\n}, function(err,result){\n //result callback\n} );\n```\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ `any`\n\nReturns `true` if at least one element in the `arr` satisfies an async test.\n_The callback for each iterator call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`. Once any iterator\ncall returns `true`, the main `callback` is immediately called.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in the array\n in parallel. The iterator is passed a callback(truthValue) which must be \n called with a boolean argument once it has completed.\n* `callback(result)` - A callback which is called as soon as any iterator returns\n `true`, or after all the iterator functions have finished. Result will be\n either `true` or `false` depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ `all`\n\nReturns `true` if every element in `arr` satisfies an async test.\n_The callback for each `iterator` call only accepts a single argument of `true` or\n`false`; it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like `fs.exists`.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A truth test to apply to each item in the array\n in parallel. The iterator is passed a callback(truthValue) which must be \n called with a boolean argument once it has completed.\n* `callback(result)` - A callback which is called after all the `iterator`\n functions have finished. Result will be either `true` or `false` depending on\n the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies `iterator` to each item in `arr`, concatenating the results. Returns the\nconcatenated list. The `iterator`s are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of `arr` passed to the `iterator` function.\n\n__Arguments__\n\n* `arr` - An array to iterate over.\n* `iterator(item, callback)` - A function to apply to each item in `arr`.\n The iterator is passed a `callback(err, results)` which must be called once it \n has completed with an error (which can be `null`) and an array of results.\n* `callback(err, results)` - A callback which is called after all the `iterator`\n functions have finished, or an error occurs. Results is an array containing\n the concatenated results of the `iterator` function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as [`concat`](#concat), but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun the functions in the `tasks` array in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run, and `callback` is immediately called with the value of the error. \nOtherwise, `callback` receives an array of results when `tasks` have completed.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function, and the results will be passed to the final `callback` as an object\ninstead of an array. This can be a more readable way of handling results from\n[`series`](#series).\n\n**Note** that while many implementations preserve the order of object properties, the\n[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) \nexplicitly states that\n\n> The mechanics and order of enumerating the properties is not specified.\n\nSo if you rely on the order in which your series of functions are executed, and want\nthis to work on all platforms, consider using an array. \n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run, each function is passed\n a `callback(err, result)` it must call on completion with an error `err` (which can\n be `null`) and an optional `result` value.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the `task` callbacks.\n\n__Example__\n\n```js\nasync.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n }\n],\n// optional callback\nfunction(err, results){\n // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun the `tasks` array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main `callback` is immediately called with the value of the error.\nOnce the `tasks` have completed, the results are passed to the final `callback` as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final `callback` as an object\ninstead of an array. This can be a more readable way of handling results from\n[`parallel`](#parallel).\n\n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run. Each function is passed \n a `callback(err, result)` which it must call on completion with an error `err` \n (which can be `null`) and an optional `result` value.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n }\n],\n// optional callback\nfunction(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n }\n},\nfunction(err, results) {\n // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n\n### parallelLimit(tasks, limit, [callback])\n\nThe same as [`parallel`](#parallel), only `tasks` are executed in parallel \nwith a maximum of `limit` tasks executing at any time.\n\nNote that the `tasks` are not executed in batches, so there is no guarantee that \nthe first `limit` tasks will complete before any others are started.\n\n__Arguments__\n\n* `tasks` - An array or object containing functions to run, each function is passed \n a `callback(err, result)` it must call on completion with an error `err` (which can\n be `null`) and an optional `result` value.\n* `limit` - The maximum number of `tasks` to run at any time.\n* `callback(err, results)` - An optional callback to run once all the functions\n have completed. This function gets a results array (or object) containing all \n the result arguments passed to the `task` callbacks.\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,\nor an error occurs.\n\n__Arguments__\n\n* `test()` - synchronous truth test to perform before each execution of `fn`.\n* `fn(callback)` - A function which is called each time `test` passes. The function is\n passed a `callback(err)`, which must be called once it has completed with an \n optional `err` argument.\n* `callback(err)` - A callback which is called after the test fails and repeated\n execution of `fn` has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n);\n```\n\n---------------------------------------\n\n\n### doWhilst(fn, test, callback)\n\nThe post-check version of [`whilst`](#whilst). To reflect the difference in \nthe order of operations, the arguments `test` and `fn` are switched. \n\n`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,\nor an error occurs.\n\nThe inverse of [`whilst`](#whilst).\n\n---------------------------------------\n\n\n### doUntil(fn, test, callback)\n\nLike [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n\n### forever(fn, errback)\n\nCalls the asynchronous function `fn` with a callback parameter that allows it to\ncall itself again, in series, indefinitely.\n\nIf an error is passed to the callback then `errback` is called with the\nerror, and execution stops, otherwise it will never be called.\n\n```js\nasync.forever(\n function(next) {\n // next is suitable for passing to things that need a callback(err [, whatever]);\n // it will result in this function being called again.\n },\n function(err) {\n // if next is called with a value in its first parameter, it will appear\n // in here as 'err', and execution will stop.\n }\n);\n```\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns the `tasks` array of functions in series, each passing their results to the next in\nthe array. However, if any of the `tasks` pass an error to their own callback, the\nnext function is not executed, and the main `callback` is immediately called with\nthe error.\n\n__Arguments__\n\n* `tasks` - An array of functions to run, each function is passed a \n `callback(err, result1, result2, ...)` it must call on completion. The first\n argument is an error (which can be `null`) and any further arguments will be \n passed as arguments in order to the next task.\n* `callback(err, [results])` - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n // arg1 now equals 'one' and arg2 now equals 'two'\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n], function (err, result) {\n // result now equals 'done' \n});\n```\n\n---------------------------------------\n\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions `f()`, `g()`, and `h()` would produce the result of\n`f(g(h()))`, only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* `functions...` - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n setTimeout(function () {\n callback(null, n + 1);\n }, 10);\n}\n\nfunction mul3(n, callback) {\n setTimeout(function () {\n callback(null, n * 3);\n }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n // result now equals 15\n});\n```\n\n---------------------------------------\n\n### seq(fn1, fn2...)\n\nVersion of the compose function that is more natural to read.\nEach following function consumes the return value of the latter function. \n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\n// Requires lodash (or underscore), express3 and dresende's orm2.\n// Part of an app, that fetches cats of the logged user.\n// This example uses `seq` function to avoid overnesting and error \n// handling clutter.\napp.get('/cats', function(request, response) {\n function handleError(err, data, callback) {\n if (err) {\n console.error(err);\n response.json({ status: 'error', message: err.message });\n }\n else {\n callback(data);\n }\n }\n var User = request.models.User;\n async.seq(\n _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))\n handleError,\n function(user, fn) {\n user.getCats(fn); // 'getCats' has signature (callback(err, data))\n },\n handleError,\n function(cats) {\n response.json({ status: 'ok', message: 'Cats found', data: cats });\n }\n )(req.session.user_id);\n }\n});\n```\n\n---------------------------------------\n\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling \n`callback` after all functions have completed. If you only provide the first\nargument, then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* `fns` - the asynchronous functions to all call with the same arguments\n* `args...` - any number of separate arguments to pass to the function\n* `callback` - the final argument should be the callback, called when all\n functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n buckets,\n async.applyEach([enableSearch, updateSchema]),\n callback\n);\n```\n\n---------------------------------------\n\n\n### applyEachSeries(arr, iterator, callback)\n\nThe same as [`applyEach`](#applyEach) only the functions are applied in series.\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a `queue` object with the specified `concurrency`. Tasks added to the\n`queue` are processed in parallel (up to the `concurrency` limit). If all\n`worker`s are in progress, the task is queued until one becomes available. \nOnce a `worker` completes a `task`, that `task`'s callback is called.\n\n__Arguments__\n\n* `worker(task, callback)` - An asynchronous function for processing a queued\n task, which must call its `callback(err)` argument when finished, with an \n optional `error` as an argument.\n* `concurrency` - An `integer` for determining how many `worker` functions should be\n run in parallel.\n\n__Queue objects__\n\nThe `queue` object returned by this function has the following properties and\nmethods:\n\n* `length()` - a function returning the number of items waiting to be processed.\n* `started` - a function returning whether or not any items have been pushed and processed by the queue\n* `running()` - a function returning the number of items currently being processed.\n* `idle()` - a function returning false if there are items waiting or being processed, or true if not.\n* `concurrency` - an integer for determining how many `worker` functions should be\n run in parallel. This property can be changed after a `queue` is created to\n alter the concurrency on-the-fly.\n* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once \n the `worker` has finished processing the task. Instead of a single task, a `tasks` array\n can be submitted. The respective callback is used for every task in the list.\n* `unshift(task, [callback])` - add a new task to the front of the `queue`.\n* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, \n and further tasks will be queued.\n* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`.\n* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`.\n* `paused` - a boolean for determining whether the queue is in a paused state\n* `pause()` - a function that pauses the processing of tasks until `resume()` is called.\n* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.\n* `kill()` - a function that empties remaining tasks from the queue forcing it to go idle.\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n});\n```\n\n\n---------------------------------------\n\n\n### priorityQueue(worker, concurrency)\n\nThe same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:\n\n* `push(task, priority, [callback])` - `priority` should be a number. If an array of\n `tasks` is given, all tasks will be assigned the same priority.\n* The `unshift` method was removed.\n\n---------------------------------------\n\n\n### cargo(worker, [payload])\n\nCreates a `cargo` object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the `payload` limit). If the\n`worker` is in progress, the task is queued until it becomes available. Once\nthe `worker` has completed some tasks, each callback of those tasks is called.\nCheck out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.\n\nWhile [queue](#queue) passes only one task to one of a group of workers\nat a time, cargo passes an array of tasks to a single worker, repeating\nwhen the worker is finished.\n\n__Arguments__\n\n* `worker(tasks, callback)` - An asynchronous function for processing an array of\n queued tasks, which must call its `callback(err)` argument when finished, with \n an optional `err` argument.\n* `payload` - An optional `integer` for determining how many tasks should be\n processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe `cargo` object returned by this function has the following properties and\nmethods:\n\n* `length()` - A function returning the number of items waiting to be processed.\n* `payload` - An `integer` for determining how many tasks should be\n process per round. This property can be changed after a `cargo` is created to\n alter the payload on-the-fly.\n* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called\n once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` \n can be submitted. The respective callback is used for every task in the list.\n* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued.\n* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`.\n* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`.\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n for(var i=0; i\n### auto(tasks, [callback])\n\nDetermines the best order for running the functions in `tasks`, based on their \nrequirements. Each function can optionally depend on other functions being completed \nfirst, and each function is run as soon as its requirements are satisfied. \n\nIf any of the functions pass an error to their callback, it will not \ncomplete (so any other functions depending on it will not run), and the main \n`callback` is immediately called with the error. Functions also receive an \nobject containing the results of functions which have completed so far.\n\nNote, all functions are called with a `results` object as a second argument, \nso it is unsafe to pass functions in the `tasks` object which cannot handle the\nextra argument. \n\nFor example, this snippet of code:\n\n```js\nasync.auto({\n readData: async.apply(fs.readFile, 'data.txt', 'utf-8')\n}, callback);\n```\n\nwill have the effect of calling `readFile` with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to `readFile` in a function which does not forward the \n`results` object:\n\n```js\nasync.auto({\n readData: function(cb, results){\n fs.readFile('data.txt', 'utf-8', cb);\n }\n}, callback);\n```\n\n__Arguments__\n\n* `tasks` - An object. Each of its properties is either a function or an array of\n requirements, with the function itself the last item in the array. The object's key\n of a property serves as the name of the task defined by that property,\n i.e. can be used when specifying requirements for other tasks.\n The function receives two arguments: (1) a `callback(err, result)` which must be \n called when finished, passing an `error` (which can be `null`) and the result of \n the function's execution, and (2) a `results` object, containing the results of\n the previously executed functions.\n* `callback(err, results)` - An optional callback which is called when all the\n tasks have been completed. It receives the `err` argument if any `tasks` \n pass an error to their callback. Results are always returned; however, if \n an error occurs, no further `tasks` will be performed, and the results\n object will only contain partial results.\n\n\n__Example__\n\n```js\nasync.auto({\n get_data: function(callback){\n console.log('in get_data');\n // async code to get some data\n callback(null, 'data', 'converted to array');\n },\n make_folder: function(callback){\n console.log('in make_folder');\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n callback(null, 'folder');\n },\n write_file: ['get_data', 'make_folder', function(callback, results){\n console.log('in write_file', JSON.stringify(results));\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, 'filename');\n }],\n email_link: ['write_file', function(callback, results){\n console.log('in email_link', JSON.stringify(results));\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n callback(null, {'file':results.write_file, 'email':'user@example.com'});\n }]\n}, function(err, results) {\n console.log('err = ', err);\n console.log('results = ', results);\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n function(callback){\n console.log('in get_data');\n // async code to get some data\n callback(null, 'data', 'converted to array');\n },\n function(callback){\n console.log('in make_folder');\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n callback(null, 'folder');\n }\n],\nfunction(err, results){\n async.series([\n function(callback){\n console.log('in write_file', JSON.stringify(results));\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n results.push('filename');\n callback(null);\n },\n function(callback){\n console.log('in email_link', JSON.stringify(results));\n // once the file is written let's email a link to it...\n callback(null, {'file':results.pop(), 'email':'user@example.com'});\n }\n ]);\n});\n```\n\nFor a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding\nnew tasks much easier (and the code more readable).\n\n\n---------------------------------------\n\n\n### retry([times = 5], task, [callback])\n\nAttempts to get a successful response from `task` no more than `times` times before\nreturning an error. If the task is successful, the `callback` will be passed the result\nof the successfull task. If all attemps fail, the callback will be passed the error and\nresult (if any) of the final attempt.\n\n__Arguments__\n\n* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5.\n* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`\n which must be called when finished, passing `err` (which can be `null`) and the `result` of \n the function's execution, and (2) a `results` object, containing the results of\n the previously executed functions (if nested inside another control flow).\n* `callback(err, results)` - An optional callback which is called when the\n task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.\n\nThe [`retry`](#retry) function can be used as a stand-alone control flow by passing a\ncallback, as shown below:\n\n```js\nasync.retry(3, apiMethod, function(err, result) {\n // do something with the result\n});\n```\n\nIt can also be embeded within other control flow functions to retry individual methods\nthat are not as reliable, like this:\n\n```js\nasync.auto({\n users: api.getUsers.bind(api),\n payments: async.retry(3, api.getPayments.bind(api))\n}, function(err, results) {\n // do something with the results\n});\n```\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the `tasks` array,\nreturning a continuation to call the next one after that. It's also possible to\n“peek” at the next iterator with `iterator.next()`.\n\nThis function is used internally by the `async` module, but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* `tasks` - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied. \n\nUseful as a shorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* `function` - The function you want to eventually apply all arguments to.\n* `arguments...` - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls `callback` on a later loop around the event loop. In Node.js this just\ncalls `process.nextTick`; in the browser it falls back to `setImmediate(callback)`\nif available, otherwise `setTimeout(callback, 0)`, which means other higher priority\nevents may precede the execution of `callback`.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* `callback` - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n\n### times(n, callback)\n\nCalls the `callback` function `n` times, and accumulates results in the same manner\nyou would use with [`map`](#map).\n\n__Arguments__\n\n* `n` - The number of times to run the function.\n* `callback` - The function to call `n` times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n callback(null, {\n id: 'user' + id\n })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n createUser(n, function(err, user) {\n next(err, user)\n })\n}, function(err, users) {\n // we should now have 5 users\n});\n```\n\n\n### timesSeries(n, callback)\n\nThe same as [`times`](#times), only the iterator is applied to each item in `arr` in\nseries. The next `iterator` is only called once the current one has completed. \nThe results array will be in the same order as the original.\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an `async` function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* `fn` - The function to proxy and cache results from.\n* `hasher` - Tn optional function for generating a custom hash for storing\n results. It has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n // callback\n});\n```\n\n\n### unmemoize(fn)\n\nUndoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized\nform. Handy for testing.\n\n__Arguments__\n\n* `fn` - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an `async` function to the `console`. Only works in Node.js or\nin browsers that support `console.log` and `console.error` (such as FF and Chrome).\nIf multiple arguments are returned from the async function, `console.log` is\ncalled on each argument in order.\n\n__Arguments__\n\n* `function` - The function you want to eventually apply all arguments to.\n* `arguments...` - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an `async` function to the `console` using `console.dir` to\ndisplay the properties of the resulting object. Only works in Node.js or\nin browsers that support `console.dir` and `console.error` (such as FF and Chrome).\nIf multiple arguments are returned from the async function, `console.dir` is\ncalled on each argument in order.\n\n__Arguments__\n\n* `function` - The function you want to eventually apply all arguments to.\n* `arguments...` - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of `async` back to its original value, returning a reference to the\n`async` object.\n",
"readmeFilename": "README.md",
"homepage": "https://github.com/caolan/async",
- "_id": "async@0.1.22",
- "_shasum": "0fc1aaa088a0e3ef0ebe2d8831bab0dcf8845061",
- "_from": "async@0.1.22",
- "_resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz",
- "scripts": {}
+ "_id": "async@0.9.0",
+ "_shasum": "ac3613b1da9bed1b47510bb4651b8931e47146c7",
+ "_from": "async@0.9.0",
+ "_resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz"
}
diff --git a/node_modules/catharsis/node_modules/underscore-contrib/package.json b/node_modules/catharsis/node_modules/underscore-contrib/package.json
index 41c958f5..53f932bc 100644
--- a/node_modules/catharsis/node_modules/underscore-contrib/package.json
+++ b/node_modules/catharsis/node_modules/underscore-contrib/package.json
@@ -30,33 +30,14 @@
"test": "node ./node_modules/grunt-cli/bin/grunt test"
},
"homepage": "https://github.com/documentcloud/underscore-contrib",
+ "readme": "underscore-contrib\n==================\n\nThe brass buckles on Underscore's utility belt -- a contributors' library for [Underscore](http://underscorejs.org/).\n\nLinks\n-----\n\n * [Documentation](http://documentcloud.github.io/underscore-contrib/)\n * [Source repository](https://github.com/documentcloud/underscore-contrib)\n * [Tickets and bug reports](https://github.com/documentcloud/underscore-contrib/issues?state=open)\n * [Maintainer's website](http://www.fogus.me)\n\nWhy underscore-contrib?\n-----------------------\n\nWhile Underscore provides a bevy of useful tools to support functional programming in JavaScript, it can't\n(and shouldn't) be everything to everyone. Underscore-contrib is intended as a home for functions that, for\nvarious reasons, don't belong in Underscore proper. In particular, it aims to be:\n\n * a home for functions that are limited in scope, but solve certain point problems, and\n * a proving ground for features that belong in Underscore proper, but need some advocacy and/or evolution\n(or devolution) to get them there.\n\nUse\n---\n\nFirst, you’ll need Underscore. Then you can grab the relevant underscore-contrib libraries and simply add\nsomething\nlike the following to your pages:\n\n \n \n\nAt the moment there are no cross-contrib dependencies (i.e. each library can stand by itself), but that may\nchange in the future.\n\nContributing\n------------\n\nThere is still a lot of work to do around perf, documentation, examples, testing and distribution so any help\nin those areas is welcomed. Pull requests are accepted, but please search the [issues](https://github.com/documentcloud/underscore-contrib/issues)\nbefore proposing a new sub-contrib or addition. Additionally, all patches and proposals should have strong\ndocumentation, motivating cases and tests. It would be nice if we could not only provide useful tools built on\nUnderscore, but also provide an educational experience for why and how one might use them.\n\nOther (potentially) useful sub-contribs include the following:\n\n * String utilities\n * Date/time utilities\n * Validators\n * Iterators\n * Generators\n * Promises\n * Monads\n * Currying\n * Laziness\n * Multimethods\n\nWhat do these mean? Well, that’s up for discussion. :-)\n",
+ "readmeFilename": "README.md",
"description": "underscore-contrib ==================",
"bugs": {
"url": "https://github.com/documentcloud/underscore-contrib/issues"
},
"_id": "underscore-contrib@0.3.0",
- "dist": {
- "shasum": "665b66c24783f8fa2b18c9f8cbb0e2c7d48c26c7",
- "tarball": "http://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz"
- },
- "_from": "underscore-contrib@~0.3.0",
- "_npmVersion": "1.3.21",
- "_npmUser": {
- "name": "joshuacc",
- "email": "joshua.clanton@gmail.com"
- },
- "maintainers": [
- {
- "name": "fogus",
- "email": "mefogus@gmail.com"
- },
- {
- "name": "joshuacc",
- "email": "joshua.clanton@gmail.com"
- }
- ],
- "directories": {},
"_shasum": "665b66c24783f8fa2b18c9f8cbb0e2c7d48c26c7",
- "_resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
- "readme": "ERROR: No README data found!"
+ "_from": "underscore-contrib@~0.3.0",
+ "_resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz"
}
diff --git a/node_modules/catharsis/package.json b/node_modules/catharsis/package.json
index 5e2360bd..7299c4b3 100644
--- a/node_modules/catharsis/package.json
+++ b/node_modules/catharsis/package.json
@@ -1,5 +1,5 @@
{
- "version": "0.8.5",
+ "version": "0.8.6",
"name": "catharsis",
"description": "A JavaScript parser for Google Closure Compiler and JSDoc type expressions.",
"author": {
@@ -36,11 +36,11 @@
"url": "http://github.com/hegemonic/catharsis/raw/master/LICENSE"
}
],
- "readme": "# Catharsis #\n\nA JavaScript parser for\n[Google Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler#types)\nand [JSDoc](https://github.com/jsdoc3/jsdoc) type expressions.\n\nCatharsis is designed to be:\n\n+ **Accurate**. Catharsis is based on a [PEG.js](http://pegjs.majda.cz/) grammar that's designed to\nhandle any valid type expression. It uses a [Mocha](http://visionmedia.github.com/mocha/) test suite\nto verify the parser's accuracy.\n+ **Fast**. Parse results are cached, so the parser is invoked only when necessary.\n+ **Flexible**. Catharsis can convert a parse result back into a type expression, or into a\ndescription of the type expression. In addition, Catharsis can parse\n[JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.\n\n\n## Example ##\n\n```js\nvar catharsis = require('catharsis');\n\n// Google Closure Compiler parsing\nvar type = '!Object';\nvar parsedType;\ntry {\n parsedType = catharsis.parse(type); // {\"type\":\"NameExpression,\"name\":\"Object\",\"nullable\":false}\n} catch(e) {\n console.error('unable to parse %s: %s', type, e);\n}\n\n// JSDoc-style type expressions enabled\nvar jsdocType = 'string[]'; // Closure Compiler expects Array.\nvar parsedJsdocType;\ntry {\n parsedJsdocType = catharsis.parse(jsdocType, {jsdoc: true});\n} catch (e) {\n console.error('unable to parse %s: %s', jsdocType, e);\n}\n\n// Converting parse results back to type expressions\ncatharsis.stringify(parsedType); // !Object\ncatharsis.stringify(parsedJsdocType); // string[]\ncatharsis.stringify(parsedJsdocType, {restringify: true}); // Array.\n\n// Converting parse results to descriptions of the type expression\ncatharsis.describe(parsedType).simple; // non-null Object\ncatharsis.describe(parsedJsdocType).simple; // Array of string\n```\n\nSee the [test/specs directory](test/specs) for more examples of Catharsis' parse results.\n\n\n## Methods ##\n\n### parse(typeExpression, options) ###\nParse a type expression, and return the parse results. Throws an error if the type expression cannot\nbe parsed.\n\nWhen called without options, Catharsis attempts to parse type expressions in the same way as\nClosure Compiler. When the `jsdoc` option is enabled, Catharsis can also parse several kinds of\ntype expressions that are permitted in [JSDoc](https://github.com/jsdoc3/jsdoc):\n\n+ The string `function` is treated as a function type with no parameters.\n+ In a function type with repeatable parameters, the names of repeatable parameters are not required\nto be enclosed in square brackets (for example, `function(...foo)` is allowed).\n+ The period may be omitted from type applications. For example, `Array.` and\n`Array` will be parsed in the same way.\n+ You may append `[]` to a name expression (for example, `string[]`) to interpret it as a type\napplication with the expression `Array` (for example, `Array.`).\n+ Name expressions may contain the characters `#`, `~`, `:`, and `/`.\n+ Name expressions may contain a suffix that is similar to a function signature (for example,\n`MyClass(foo, bar)`).\n+ Name expressions may contain a reserved word.\n+ Record types may use types other than name expressions for keys.\n\n#### Parameters ####\n+ `type`: A string containing a Closure Compiler type expression.\n+ `options`: Options for parsing the type expression.\n + `options.jsdoc`: Specifies whether to enable parsing of JSDoc-style type expressions. Defaults\n to `false`.\n + `options.useCache`: Specifies whether to use the cache of parsed types. Defaults to `true`.\n\n#### Returns ####\nAn object containing the parse results. See the [test/specs directory](test/specs) for examples of\nthe parse results for different type expressions.\n\nThe object also includes two non-enumerable properties:\n\n+ `jsdoc`: A boolean indicating whether the type expression was parsed with JSDoc support enabled.\n+ `typeExpression`: A string containing the type expression that was parsed.\n\n### stringify(parsedType, options) ###\nStringify `parsedType`, and return the type expression. If validation is enabled, throws an error if\nthe stringified type expression cannot be parsed.\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for stringifying the parse results.\n + `options.cssClass`: Synonym for `options.linkClass`. Deprecated in version 0.8.0; will be\n removed in a future version.\n + `options.htmlSafe`: Specifies whether to return an HTML-safe string that replaces left angle\n brackets (`<`) with the corresponding entity (`<`). **Note**: Characters in name expressions\n are not escaped.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `` tag that links to the URI. If `options.linkClass` is specified, the `` tag will\n include a `class` attribute. **Note**: When using this option, parsed types are always\n restringified, and the resulting string is not cached.\n + `options.restringify`: Forces Catharsis to restringify the parsed type. If this option is not\n specified, and the parsed type object includes a `typeExpression` property, Catharsis will\n return the `typeExpression` property without modification when possible. Defaults to `false`.\n + `options.useCache`: Specifies whether to use the cache of stringified type expressions.\n Defaults to `true`.\n + `options.validate`: Specifies whether to validate the stringified parse results by attempting\n to parse them as a type expression. If the stringified results are not parsable by default, you\n must also provide the appropriate options to pass to the `parse()` method. Defaults to `false`.\n\n#### Returns ####\nA string containing the type expression.\n\n### describe(parsedType, options) ###\nConvert a parsed type to a description of the type expression. This method is especially useful if\nyour users are not familiar with the syntax for type expressions.\n\nThe `describe()` method returns the description in two formats:\n\n+ **Simple format**. A string that provides a complete description of the type expression.\n+ **Extended format**. An object that separates out some of the details about the outermost type\nexpression, such as whether the type is optional, nullable, or repeatable.\n\nFor example, if you call `describe('?function(new:MyObject, string)=')`, it returns the following\nobject:\n\n```js\n{\n simple: 'optional nullable function(constructs MyObject, string)',\n extended: {\n description: 'function(string)',\n modifiers: {\n functionNew: 'Returns MyObject when called with new.',\n functionThis: '',\n optional: 'Optional.',\n nullable: 'May be null.',\n repeatable: ''\n },\n returns: ''\n }\n}\n```\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for creating the description.\n + `options.codeClass`: A CSS class to add to the tag that is wrapped around type names. Used\n only if `options.codeTag` is provided. By default, no CSS class is added.\n + `options.codeTag`: The name of an HTML tag (for example, `code`) to wrap around type names.\n For example, if this option is set to `code`, the type expression `Array.` would have\n the simple description `Array of string`.\n + `options.language`: A string identifying the language in which to generate the description.\n The identifier should be an\n [ISO 639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (for example,\n `en`). It can optionally be followed by a hyphen and an\n [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (for example,\n `en-US`). If you use values other than `en`, you must provide translation resources in\n `options.resources`. Defaults to `en`.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `` tag that links to the URI. If `options.linkClass` is specified, the `` tag will\n include a `class` attribute. **Note**: When using this option, the description is not cached.\n + `options.resources`: An object that specifies how to describe type expressions for a given\n language. The object's property names should use the same format as `options.language`. Each\n property should contain an object in the same format as the translation resources in\n [res/en.json](res/en.json). If you specify a value for `options.resources.en`, it will override\n the defaults in [res/en.json](res/en.json).\n + `options.useCache`: Specifies whether to use the cache of descriptions. Defaults to `true`.\n\n### Returns ###\nAn object with the following properties:\n\n+ `simple`: A string that provides a complete description of the type expression.\n+ `extended`: An object containing details about the outermost type expression.\n + `extended.description`: A string that provides a basic description of the type expression,\n excluding the information contained in other properties.\n + `extended.modifiers`: Information about modifiers that apply to the type expression.\n + `extended.modifiers.functionNew`: A string describing what a function returns when called\n with `new`. Used only for function types.\n + `extended.modifiers.functionThis`: A string describing what the keyword `this` refers to\n within a function. Used only for function types.\n + `extended.modifiers.nullable`: A string indicating whether the type is nullable or\n non-nullable.\n + `extended.modifiers.optional`: A string indicating whether the type is optional.\n + `extended.modifiers.repeatable`: A string indicating whether the type can be provided\n + `extended.returns`: A string describing the function's return value. Used only for function\n types.\n\n\n## Installation ##\n\nWith [npm](http://npmjs.org):\n\n npm install catharsis\n\nOr without:\n\n git clone git://github.com/hegemonic/catharsis.git\n cd catharsis\n npm install\n\n\n## Roadmap and known issues ##\n\nTake a look at the [issue tracker](https://github.com/hegemonic/catharsis/issues) to see what's in\nstore for Catharsis.\n\nBug reports, feature requests, and pull requests are always welcome! If you're working on a large\npull request, please contact me in advance so I can help things go smoothly.\n\n**Note**: The parse tree's format should not be considered final until Catharsis reaches version\n1.0. I'll do my best to provide release notes for any changes.\n\n\n## Changelog ##\n\n+ 0.8.5 (December 2014): Added support for postfix nullable/non-nullable operators combined with the\noptional operator (for example, `foo?=`).\n+ 0.8.4 (December 2014): JSDoc-style nested arrays (for example, `number[][]`) are now parsed\ncorrectly when JSDoc-style type expressions are enabled.\n+ 0.8.3 (October 2014):\n + Type applications are no longer required to include a period (`.`) as a separator, regardless\n of whether JSDoc-style type expressions are enabled.\n + Type unions that are not enclosed in parentheses can now include the repeatable (`...`)\n modifier when JSDoc-style type expressions are enabled.\n + Name expressions may now be enclosed in single or double quotation marks when JSDoc-style\n type expressions are enabled.\n+ 0.8.2 (June 2014): Fixed a compatibility issue with the JSDoc fork of Mozilla Rhino.\n+ 0.8.1 (June 2014): Added support for type unions that are not enclosed in parentheses, and that\ncontain nullable or non-nullable modifiers (for example, `!string|!number`).\n+ 0.8.0 (May 2014):\n + Added a `describe()` method, which converts a parsed type to a description of the type.\n + Added a `linkClass` option to the `stringify()` method, and deprecated the existing `cssClass`\n option. The `cssClass` option will be removed in a future release.\n + Clarified and corrected several sections in the `README`.\n+ 0.7.1 (April 2014): In record types, property names that begin with a keyword (for example,\n`undefinedHTML`) are now parsed correctly when JSDoc-style type expressions are enabled.\n+ 0.7.0 (October 2013):\n + Repeatable type expressions other than name expressions (for example, `...function()`) are now\n parsed and stringified correctly.\n + Type expressions that are both repeatable and either nullable or non-nullable (for example,\n `...!number`) are now parsed and stringified correctly.\n + Name expressions are now parsed correctly when they match a property name in an object\n instance (for example, `constructor`).\n+ 0.6.0 (September 2013): Added support for the type expression `function[]` when JSDoc-style type\nexpressions are enabled.\n+ 0.5.6 (April 2013):\n + For consistency with Google Closure Library, parentheses are no longer required around type\n unions. (In previous versions, the parentheses could be omitted when JSDoc support was enabled.)\n + For consistency with Google Closure Library, you can now use postfix notation for the `?`\n (nullable) and `!` (non-nullable) modifiers. For example, `?string` and `string?` are now\n treated as equivalent.\n + String literals and numeric literals are now allowed as property names within name\n expressions. For example, the name expression `Foo.\"bar\"` is now parsed correctly.\n+ 0.5.5 (April 2013): Corrected a parsing issue with name expressions that end with a value enclosed\nin parentheses.\n+ 0.5.4 (April 2013):\n + Repeatable literals (for example, `...*`) are now parsed correctly.\n + When JSDoc-style type expressions are enabled, a name expression can now contain a value\n enclosed in parentheses at the end of the name expression (for example, `MyClass(2)`).\n+ 0.5.3 (March 2013): The `parse()` method now correctly parses name expressions that contain\nhyphens.\n+ 0.5.2 (March 2013): The `parse()` method now correctly parses function types when JSDoc-style type\nexpressions are enabled.\n+ 0.5.1 (March 2013): Newlines and extra spaces are now removed from type expressions before they\nare parsed.\n+ 0.5.0 (March 2013):\n + The `parse()` method's `lenient` option has been renamed to `jsdoc`. **Note**: This change is\n not backwards-compatible with previous versions.\n + The `stringify()` method now accepts `cssClass` and `links` options, which you can use to\n add HTML links to a type expression.\n+ 0.4.3 (March 2013):\n + The `stringify()` method no longer caches HTML-safe type expressions as if they were normal\n type expressions.\n + The `stringify()` method's options parameter may now include an `options.restringify`\n property, and the behavior of the `options.useCache` property has changed.\n+ 0.4.2 (March 2013):\n + When lenient parsing is enabled, name expressions can now contain the characters `:` and `/`.\n + When lenient parsing is enabled, a name expression followed by `[]` (for example, `string[]`)\n will be interpreted as a type application with the expression `Array` (for example,\n `Array.`).\n+ 0.4.1 (March 2013):\n + The `parse()` and `stringify()` methods now honor all of the specified options.\n + When lenient parsing is enabled, name expressions can now contain a reserved word.\n+ 0.4.0 (March 2013):\n + Catharsis now supports a lenient parsing option that can parse several kinds of malformed type\n expressions. See the documentation for details.\n + The objects containing parse results are now frozen.\n + The objects containing parse results now have two non-enumerable properties:\n + `lenient`: A boolean indicating whether the type expression was parsed in lenient mode.\n + `typeExpression`: A string containing the original type expression.\n + The `stringify()` method now honors the `useCache` option. If a parsed type includes a\n `typeExpression` property, and `useCache` is not set to `false`, the stringified type will be\n identical to the original type expression.\n+ 0.3.1 (March 2013): Type expressions that begin with a reserved word, such as `integer`, are now\nparsed correctly.\n+ 0.3.0 (March 2013):\n + The `parse()` and `stringify()` methods are now synchronous, and the `parseSync()` and\n `stringifySync()` methods have been removed. **Note**: This change is not backwards-compatible\n with previous versions.\n + The parse results now use a significantly different format from previous versions. The new\n format is more expressive and is similar, but not identical, to the format used by the\n [doctrine](https://github.com/Constellation/doctrine) parser. **Note**: This change is not\n backwards-compatible with previous versions.\n + Name expressions that contain a reserved word now include a `reservedWord: true` property.\n + Union types that are optional or nullable, or that can be passed a variable number of times,\n are now parsed and stringified correctly.\n + Optional function types and record types are now parsed and stringified correctly.\n + Function types now longer include `new` or `this` properties unless the properties are defined\n in the type expression. In addition, the `new` and `this` properties can now use any type\n expression.\n + In record types, the key for a field type can now use any type expression.\n + Standalone single-character literals, such as ALL (`*`), are now parsed and stringified\n correctly.\n + `null` and `undefined` literals with additional properties, such as `repeatable`, are now\n stringified correctly.\n+ 0.2.0 (November 2012):\n + Added `stringify()` and `stringifySync()` methods, which convert a parsed type to a type\n expression.\n + Simplified the parse results for function signatures. **Note**: This change is not\n backwards-compatible with previous versions.\n + Corrected minor errors in README.md.\n+ 0.1.1 (November 2012): Added `opts` argument to `parse()` and `parseSync()` methods. **Note**: The\nchange to `parse()` is not backwards-compatible with previous versions.\n+ 0.1.0 (November 2012): Initial release.\n\n## License ##\n\n[MIT license](https://github.com/hegemonic/catharsis/blob/master/LICENSE).\n",
+ "readme": "# Catharsis #\n\nA JavaScript parser for\n[Google Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler#types)\nand [JSDoc](https://github.com/jsdoc3/jsdoc) type expressions.\n\nCatharsis is designed to be:\n\n+ **Accurate**. Catharsis is based on a [PEG.js](http://pegjs.majda.cz/) grammar that's designed to\nhandle any valid type expression. It uses a [Mocha](http://visionmedia.github.com/mocha/) test suite\nto verify the parser's accuracy.\n+ **Fast**. Parse results are cached, so the parser is invoked only when necessary.\n+ **Flexible**. Catharsis can convert a parse result back into a type expression, or into a\ndescription of the type expression. In addition, Catharsis can parse\n[JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.\n\n\n## Example ##\n\n```js\nvar catharsis = require('catharsis');\n\n// Google Closure Compiler parsing\nvar type = '!Object';\nvar parsedType;\ntry {\n parsedType = catharsis.parse(type); // {\"type\":\"NameExpression,\"name\":\"Object\",\"nullable\":false}\n} catch(e) {\n console.error('unable to parse %s: %s', type, e);\n}\n\n// JSDoc-style type expressions enabled\nvar jsdocType = 'string[]'; // Closure Compiler expects Array.\nvar parsedJsdocType;\ntry {\n parsedJsdocType = catharsis.parse(jsdocType, {jsdoc: true});\n} catch (e) {\n console.error('unable to parse %s: %s', jsdocType, e);\n}\n\n// Converting parse results back to type expressions\ncatharsis.stringify(parsedType); // !Object\ncatharsis.stringify(parsedJsdocType); // string[]\ncatharsis.stringify(parsedJsdocType, {restringify: true}); // Array.\n\n// Converting parse results to descriptions of the type expression\ncatharsis.describe(parsedType).simple; // non-null Object\ncatharsis.describe(parsedJsdocType).simple; // Array of string\n```\n\nSee the [test/specs directory](test/specs) for more examples of Catharsis' parse results.\n\n\n## Methods ##\n\n### parse(typeExpression, options) ###\nParse a type expression, and return the parse results. Throws an error if the type expression cannot\nbe parsed.\n\nWhen called without options, Catharsis attempts to parse type expressions in the same way as\nClosure Compiler. When the `jsdoc` option is enabled, Catharsis can also parse several kinds of\ntype expressions that are permitted in [JSDoc](https://github.com/jsdoc3/jsdoc):\n\n+ The string `function` is treated as a function type with no parameters.\n+ In a function type with repeatable parameters, the names of repeatable parameters are not required\nto be enclosed in square brackets (for example, `function(...foo)` is allowed).\n+ The period may be omitted from type applications. For example, `Array.` and\n`Array` will be parsed in the same way.\n+ You may append `[]` to a name expression (for example, `string[]`) to interpret it as a type\napplication with the expression `Array` (for example, `Array.`).\n+ Name expressions may contain the characters `#`, `~`, `:`, and `/`.\n+ Name expressions may contain a suffix that is similar to a function signature (for example,\n`MyClass(foo, bar)`).\n+ Name expressions may contain a reserved word.\n+ Record types may use types other than name expressions for keys.\n\n#### Parameters ####\n+ `type`: A string containing a Closure Compiler type expression.\n+ `options`: Options for parsing the type expression.\n + `options.jsdoc`: Specifies whether to enable parsing of JSDoc-style type expressions. Defaults\n to `false`.\n + `options.useCache`: Specifies whether to use the cache of parsed types. Defaults to `true`.\n\n#### Returns ####\nAn object containing the parse results. See the [test/specs directory](test/specs) for examples of\nthe parse results for different type expressions.\n\nThe object also includes two non-enumerable properties:\n\n+ `jsdoc`: A boolean indicating whether the type expression was parsed with JSDoc support enabled.\n+ `typeExpression`: A string containing the type expression that was parsed.\n\n### stringify(parsedType, options) ###\nStringify `parsedType`, and return the type expression. If validation is enabled, throws an error if\nthe stringified type expression cannot be parsed.\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for stringifying the parse results.\n + `options.cssClass`: Synonym for `options.linkClass`. Deprecated in version 0.8.0; will be\n removed in a future version.\n + `options.htmlSafe`: Specifies whether to return an HTML-safe string that replaces left angle\n brackets (`<`) with the corresponding entity (`<`). **Note**: Characters in name expressions\n are not escaped.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `` tag that links to the URI. If `options.linkClass` is specified, the `` tag will\n include a `class` attribute. **Note**: When using this option, parsed types are always\n restringified, and the resulting string is not cached.\n + `options.restringify`: Forces Catharsis to restringify the parsed type. If this option is not\n specified, and the parsed type object includes a `typeExpression` property, Catharsis will\n return the `typeExpression` property without modification when possible. Defaults to `false`.\n + `options.useCache`: Specifies whether to use the cache of stringified type expressions.\n Defaults to `true`.\n + `options.validate`: Specifies whether to validate the stringified parse results by attempting\n to parse them as a type expression. If the stringified results are not parsable by default, you\n must also provide the appropriate options to pass to the `parse()` method. Defaults to `false`.\n\n#### Returns ####\nA string containing the type expression.\n\n### describe(parsedType, options) ###\nConvert a parsed type to a description of the type expression. This method is especially useful if\nyour users are not familiar with the syntax for type expressions.\n\nThe `describe()` method returns the description in two formats:\n\n+ **Simple format**. A string that provides a complete description of the type expression.\n+ **Extended format**. An object that separates out some of the details about the outermost type\nexpression, such as whether the type is optional, nullable, or repeatable.\n\nFor example, if you call `describe('?function(new:MyObject, string)=')`, it returns the following\nobject:\n\n```js\n{\n simple: 'optional nullable function(constructs MyObject, string)',\n extended: {\n description: 'function(string)',\n modifiers: {\n functionNew: 'Returns MyObject when called with new.',\n functionThis: '',\n optional: 'Optional.',\n nullable: 'May be null.',\n repeatable: ''\n },\n returns: ''\n }\n}\n```\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for creating the description.\n + `options.codeClass`: A CSS class to add to the tag that is wrapped around type names. Used\n only if `options.codeTag` is provided. By default, no CSS class is added.\n + `options.codeTag`: The name of an HTML tag (for example, `code`) to wrap around type names.\n For example, if this option is set to `code`, the type expression `Array.` would have\n the simple description `Array of string`.\n + `options.language`: A string identifying the language in which to generate the description.\n The identifier should be an\n [ISO 639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (for example,\n `en`). It can optionally be followed by a hyphen and an\n [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (for example,\n `en-US`). If you use values other than `en`, you must provide translation resources in\n `options.resources`. Defaults to `en`.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `` tag that links to the URI. If `options.linkClass` is specified, the `` tag will\n include a `class` attribute. **Note**: When using this option, the description is not cached.\n + `options.resources`: An object that specifies how to describe type expressions for a given\n language. The object's property names should use the same format as `options.language`. Each\n property should contain an object in the same format as the translation resources in\n [res/en.json](res/en.json). If you specify a value for `options.resources.en`, it will override\n the defaults in [res/en.json](res/en.json).\n + `options.useCache`: Specifies whether to use the cache of descriptions. Defaults to `true`.\n\n### Returns ###\nAn object with the following properties:\n\n+ `simple`: A string that provides a complete description of the type expression.\n+ `extended`: An object containing details about the outermost type expression.\n + `extended.description`: A string that provides a basic description of the type expression,\n excluding the information contained in other properties.\n + `extended.modifiers`: Information about modifiers that apply to the type expression.\n + `extended.modifiers.functionNew`: A string describing what a function returns when called\n with `new`. Used only for function types.\n + `extended.modifiers.functionThis`: A string describing what the keyword `this` refers to\n within a function. Used only for function types.\n + `extended.modifiers.nullable`: A string indicating whether the type is nullable or\n non-nullable.\n + `extended.modifiers.optional`: A string indicating whether the type is optional.\n + `extended.modifiers.repeatable`: A string indicating whether the type can be provided\n + `extended.returns`: A string describing the function's return value. Used only for function\n types.\n\n\n## Installation ##\n\nWith [npm](http://npmjs.org):\n\n npm install catharsis\n\nOr without:\n\n git clone git://github.com/hegemonic/catharsis.git\n cd catharsis\n npm install\n\n\n## Roadmap and known issues ##\n\nTake a look at the [issue tracker](https://github.com/hegemonic/catharsis/issues) to see what's in\nstore for Catharsis.\n\nBug reports, feature requests, and pull requests are always welcome! If you're working on a large\npull request, please contact me in advance so I can help things go smoothly.\n\n**Note**: The parse tree's format should not be considered final until Catharsis reaches version\n1.0. I'll do my best to provide release notes for any changes.\n\n\n## Changelog ##\n\n+ 0.8.6 (December 2014): Improved the description of the unknown type.\n+ 0.8.5 (December 2014): Added support for postfix nullable/non-nullable operators combined with the\noptional operator (for example, `foo?=`).\n+ 0.8.4 (December 2014): JSDoc-style nested arrays (for example, `number[][]`) are now parsed\ncorrectly when JSDoc-style type expressions are enabled.\n+ 0.8.3 (October 2014):\n + Type applications are no longer required to include a period (`.`) as a separator, regardless\n of whether JSDoc-style type expressions are enabled.\n + Type unions that are not enclosed in parentheses can now include the repeatable (`...`)\n modifier when JSDoc-style type expressions are enabled.\n + Name expressions may now be enclosed in single or double quotation marks when JSDoc-style\n type expressions are enabled.\n+ 0.8.2 (June 2014): Fixed a compatibility issue with the JSDoc fork of Mozilla Rhino.\n+ 0.8.1 (June 2014): Added support for type unions that are not enclosed in parentheses, and that\ncontain nullable or non-nullable modifiers (for example, `!string|!number`).\n+ 0.8.0 (May 2014):\n + Added a `describe()` method, which converts a parsed type to a description of the type.\n + Added a `linkClass` option to the `stringify()` method, and deprecated the existing `cssClass`\n option. The `cssClass` option will be removed in a future release.\n + Clarified and corrected several sections in the `README`.\n+ 0.7.1 (April 2014): In record types, property names that begin with a keyword (for example,\n`undefinedHTML`) are now parsed correctly when JSDoc-style type expressions are enabled.\n+ 0.7.0 (October 2013):\n + Repeatable type expressions other than name expressions (for example, `...function()`) are now\n parsed and stringified correctly.\n + Type expressions that are both repeatable and either nullable or non-nullable (for example,\n `...!number`) are now parsed and stringified correctly.\n + Name expressions are now parsed correctly when they match a property name in an object\n instance (for example, `constructor`).\n+ 0.6.0 (September 2013): Added support for the type expression `function[]` when JSDoc-style type\nexpressions are enabled.\n+ 0.5.6 (April 2013):\n + For consistency with Google Closure Library, parentheses are no longer required around type\n unions. (In previous versions, the parentheses could be omitted when JSDoc support was enabled.)\n + For consistency with Google Closure Library, you can now use postfix notation for the `?`\n (nullable) and `!` (non-nullable) modifiers. For example, `?string` and `string?` are now\n treated as equivalent.\n + String literals and numeric literals are now allowed as property names within name\n expressions. For example, the name expression `Foo.\"bar\"` is now parsed correctly.\n+ 0.5.5 (April 2013): Corrected a parsing issue with name expressions that end with a value enclosed\nin parentheses.\n+ 0.5.4 (April 2013):\n + Repeatable literals (for example, `...*`) are now parsed correctly.\n + When JSDoc-style type expressions are enabled, a name expression can now contain a value\n enclosed in parentheses at the end of the name expression (for example, `MyClass(2)`).\n+ 0.5.3 (March 2013): The `parse()` method now correctly parses name expressions that contain\nhyphens.\n+ 0.5.2 (March 2013): The `parse()` method now correctly parses function types when JSDoc-style type\nexpressions are enabled.\n+ 0.5.1 (March 2013): Newlines and extra spaces are now removed from type expressions before they\nare parsed.\n+ 0.5.0 (March 2013):\n + The `parse()` method's `lenient` option has been renamed to `jsdoc`. **Note**: This change is\n not backwards-compatible with previous versions.\n + The `stringify()` method now accepts `cssClass` and `links` options, which you can use to\n add HTML links to a type expression.\n+ 0.4.3 (March 2013):\n + The `stringify()` method no longer caches HTML-safe type expressions as if they were normal\n type expressions.\n + The `stringify()` method's options parameter may now include an `options.restringify`\n property, and the behavior of the `options.useCache` property has changed.\n+ 0.4.2 (March 2013):\n + When lenient parsing is enabled, name expressions can now contain the characters `:` and `/`.\n + When lenient parsing is enabled, a name expression followed by `[]` (for example, `string[]`)\n will be interpreted as a type application with the expression `Array` (for example,\n `Array.`).\n+ 0.4.1 (March 2013):\n + The `parse()` and `stringify()` methods now honor all of the specified options.\n + When lenient parsing is enabled, name expressions can now contain a reserved word.\n+ 0.4.0 (March 2013):\n + Catharsis now supports a lenient parsing option that can parse several kinds of malformed type\n expressions. See the documentation for details.\n + The objects containing parse results are now frozen.\n + The objects containing parse results now have two non-enumerable properties:\n + `lenient`: A boolean indicating whether the type expression was parsed in lenient mode.\n + `typeExpression`: A string containing the original type expression.\n + The `stringify()` method now honors the `useCache` option. If a parsed type includes a\n `typeExpression` property, and `useCache` is not set to `false`, the stringified type will be\n identical to the original type expression.\n+ 0.3.1 (March 2013): Type expressions that begin with a reserved word, such as `integer`, are now\nparsed correctly.\n+ 0.3.0 (March 2013):\n + The `parse()` and `stringify()` methods are now synchronous, and the `parseSync()` and\n `stringifySync()` methods have been removed. **Note**: This change is not backwards-compatible\n with previous versions.\n + The parse results now use a significantly different format from previous versions. The new\n format is more expressive and is similar, but not identical, to the format used by the\n [doctrine](https://github.com/Constellation/doctrine) parser. **Note**: This change is not\n backwards-compatible with previous versions.\n + Name expressions that contain a reserved word now include a `reservedWord: true` property.\n + Union types that are optional or nullable, or that can be passed a variable number of times,\n are now parsed and stringified correctly.\n + Optional function types and record types are now parsed and stringified correctly.\n + Function types now longer include `new` or `this` properties unless the properties are defined\n in the type expression. In addition, the `new` and `this` properties can now use any type\n expression.\n + In record types, the key for a field type can now use any type expression.\n + Standalone single-character literals, such as ALL (`*`), are now parsed and stringified\n correctly.\n + `null` and `undefined` literals with additional properties, such as `repeatable`, are now\n stringified correctly.\n+ 0.2.0 (November 2012):\n + Added `stringify()` and `stringifySync()` methods, which convert a parsed type to a type\n expression.\n + Simplified the parse results for function signatures. **Note**: This change is not\n backwards-compatible with previous versions.\n + Corrected minor errors in README.md.\n+ 0.1.1 (November 2012): Added `opts` argument to `parse()` and `parseSync()` methods. **Note**: The\nchange to `parse()` is not backwards-compatible with previous versions.\n+ 0.1.0 (November 2012): Initial release.\n\n## License ##\n\n[MIT license](https://github.com/hegemonic/catharsis/blob/master/LICENSE).\n",
"readmeFilename": "README.md",
- "gitHead": "e56c974cf1e20dbba4e450d7cb52d648cd069828",
"homepage": "https://github.com/hegemonic/catharsis",
- "_id": "catharsis@0.8.5",
- "_shasum": "5025a6280f8bcc27e30e5d6fb19765c6f08dd0cd",
- "_from": "catharsis@~0.8.5"
+ "_id": "catharsis@0.8.6",
+ "_shasum": "5ca786ca4efe5ff4eb063c1db7ff84b7b309a55e",
+ "_from": "catharsis@~0.8.6",
+ "_resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.6.tgz"
}
diff --git a/node_modules/catharsis/res/en.json b/node_modules/catharsis/res/en.json
index 9afb501b..77c160bd 100644
--- a/node_modules/catharsis/res/en.json
+++ b/node_modules/catharsis/res/en.json
@@ -87,5 +87,5 @@
"many": "or <%= element %>) <%= suffix %>"
}
},
- "unknown": "unknown type"
+ "unknown": "unknown"
}
diff --git a/node_modules/escape-string-regexp/package.json b/node_modules/escape-string-regexp/package.json
index 5da6f01d..63b469b5 100644
--- a/node_modules/escape-string-regexp/package.json
+++ b/node_modules/escape-string-regexp/package.json
@@ -43,7 +43,7 @@
"homepage": "https://github.com/sindresorhus/escape-string-regexp",
"_id": "escape-string-regexp@1.0.2",
"_shasum": "4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1",
- "_from": "escape-string-regexp@1.0.2",
+ "_from": "escape-string-regexp@~1.0.2",
"_npmVersion": "1.4.23",
"_npmUser": {
"name": "jbnicolai",
diff --git a/node_modules/js2xmlparser/LICENSE.md b/node_modules/js2xmlparser/LICENSE.md
index 1b76d2f6..31947432 100644
--- a/node_modules/js2xmlparser/LICENSE.md
+++ b/node_modules/js2xmlparser/LICENSE.md
@@ -1,16 +1,16 @@
-js2xmlparser is licensed under the MIT license:
-
-> Copyright © 2012 Michael Kourlas and other contributors
->
-> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
-> documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
-> rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
-> persons to whom the Software is furnished to do so, subject to the following conditions:
->
-> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
-> Software.
->
-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-> WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+js2xmlparser is licensed under the MIT license:
+
+> Copyright © 2012 Michael Kourlas and other contributors
+>
+> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+> documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+> rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+> persons to whom the Software is furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+> Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+> WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/js2xmlparser/lib/js2xmlparser.js b/node_modules/js2xmlparser/lib/js2xmlparser.js
index f96c97b6..e00748a7 100644
--- a/node_modules/js2xmlparser/lib/js2xmlparser.js
+++ b/node_modules/js2xmlparser/lib/js2xmlparser.js
@@ -1,328 +1,353 @@
-/* jshint node:true */
-
-/**
- * js2xmlparser
- * Copyright © 2012 Michael Kourlas and other contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-(function() {
- "use strict";
-
- var xmlDeclaration = true;
- var xmlVersion = "1.0";
- var xmlEncoding = "UTF-8";
- var attributeString = "@";
- var valueString = "#";
- var prettyPrinting = true;
- var indentString = "\t";
- var convertMap = {};
- var useCDATA = false;
-
- module.exports = function (root, data, options) {
- return toXML(init(root, data, options));
- };
-
- // Initialization
- var init = function(root, data, options) {
- // Set option defaults
- setOptionDefaults();
-
- // Error checking for root element
- if (typeof root !== "string") {
- throw new Error("root element must be a string");
- }
- else if (root === "") {
- throw new Error("root element cannot be empty");
- }
-
- // Error checking and variable initialization for options
- if (typeof options === "object" && options !== null) {
- if ("declaration" in options) {
- if ("include" in options.declaration) {
- if (typeof options.declaration.include === "boolean") {
- xmlDeclaration = options.declaration.include;
- }
- else {
- throw new Error("declaration.include option must be a boolean");
- }
- }
-
- if ("encoding" in options.declaration) {
- if (typeof options.declaration.encoding === "string" || options.declaration.encoding === null) {
- xmlEncoding = options.declaration.encoding;
- }
- else {
- throw new Error("declaration.encoding option must be a string or null");
- }
- }
- }
- if ("attributeString" in options) {
- if (typeof options.attributeString === "string") {
- attributeString = options.attributeString;
- }
- else {
- throw new Error("attributeString option must be a string");
- }
- }
- if ("valueString" in options) {
- if (typeof options.valueString === "string") {
- valueString = options.valueString;
- }
- else {
- throw new Error("valueString option must be a string");
- }
- }
- if ("prettyPrinting" in options) {
- if ("enabled" in options.prettyPrinting) {
- if (typeof options.prettyPrinting.enabled === "boolean") {
- prettyPrinting = options.prettyPrinting.enabled;
- }
- else {
- throw new Error("prettyPrinting.enabled option must be a boolean");
- }
- }
-
- if ("indentString" in options.prettyPrinting) {
- if (typeof options.prettyPrinting.indentString === "string") {
- indentString = options.prettyPrinting.indentString;
- }
- else {
- throw new Error("prettyPrinting.indentString option must be a string");
- }
- }
- }
- if ("convertMap" in options) {
- if (Object.prototype.toString.call(options.convertMap) === "[object Object]") {
- convertMap = options.convertMap;
- }
- else {
- throw new Error("convertMap option must be an object");
- }
- }
- if ("useCDATA" in options) {
- if (typeof options.useCDATA === "boolean") {
- useCDATA = options.useCDATA;
- }
- else {
- throw new Error("useCDATA option must be a boolean");
- }
- }
- }
-
- // Error checking and variable initialization for data
- if (typeof data !== "string" && typeof data !== "object" && typeof data !== "number" &&
- typeof data !== "boolean" && data !== null) {
- throw new Error("data must be an object (excluding arrays) or a JSON string");
- }
-
- if (data === null) {
- throw new Error("data must be an object (excluding arrays) or a JSON string");
- }
-
- if (Object.prototype.toString.call(data) === "[object Array]") {
- throw new Error("data must be an object (excluding arrays) or a JSON string");
- }
-
- if (typeof data === "string") {
- data = JSON.parse(data);
- }
-
- var tempData = {};
- tempData[root] = data; // Add root element to object
-
- return tempData;
- };
-
- // Convert object to XML
- var toXML = function(object) {
- // Initialize arguments, if necessary
- var xml = arguments[1] || "";
- var level = arguments[2] || 0;
-
- var i = null;
- var tempObject = {};
-
- for (var property in object) {
- if (object.hasOwnProperty(property)) {
- // Element name cannot start with a number
- var elementName = property;
- if (/^\d/.test(property)) {
- elementName = "_" + property;
- }
-
- // Arrays
- if (Object.prototype.toString.call(object[property]) === "[object Array]") {
- // Create separate XML elements for each array element
- for (i = 0; i < object[property].length; i++) {
- tempObject = {};
- tempObject[property] = object[property][i];
-
- xml = toXML(tempObject, xml, level);
- }
- }
- // JSON-type objects with properties
- else if (Object.prototype.toString.call(object[property]) === "[object Object]") {
- xml += addIndent("<" + elementName, level);
-
- // Add attributes
- var lengthExcludingAttributes = Object.keys(object[property]).length;
- if (Object.prototype.toString.call(object[property][attributeString]) === "[object Object]") {
- lengthExcludingAttributes -= 1;
- for (var attribute in object[property][attributeString]) {
- if (object[property][attributeString].hasOwnProperty(attribute)) {
- xml += " " + attribute + "=\"" +
- toString(object[property][attributeString][attribute], true) + "\"";
- }
- }
- }
- else if (typeof object[property][attributeString] !== "undefined") {
- // Fix for the case where an object contains a single property with the attribute string as its
- // name, but this property contains no attributes; in that case, lengthExcludingAttributes
- // should be set to zero to ensure that the object is considered an empty object for the
- // purposes of the following if statement.
- lengthExcludingAttributes -= 1;
- }
-
- if (lengthExcludingAttributes === 0) { // Empty object
- xml += addBreak("/>");
- }
- else if (lengthExcludingAttributes === 1 && valueString in object[property]) { // Value string only
- xml += addBreak(">" + toString(object[property][valueString], false) + "" + elementName + ">");
- }
- else { // Object with properties
- xml += addBreak(">");
-
- // Create separate object for each property and pass to this function
- for (var subProperty in object[property]) {
- if (object[property].hasOwnProperty(subProperty) && subProperty !== attributeString && subProperty !== valueString) {
- tempObject = {};
- tempObject[subProperty] = object[property][subProperty];
-
- xml = toXML(tempObject, xml, level + 1);
- }
- }
-
- xml += addBreak(addIndent("" + elementName + ">", level));
- }
- }
- // Everything else
- else {
- xml += addBreak(addIndent("<" + elementName + ">" + toString(object[property], false) + "" +
- elementName + ">", level));
- }
- }
- }
-
- // Finalize XML at end of process
- if (level === 0) {
- // Strip trailing whitespace
- xml = xml.replace(/\s+$/g, "");
-
- // Add XML declaration
- if (xmlDeclaration) {
- if (xmlEncoding === null) {
- xml = addBreak("") + xml;
- }
- else {
- xml = addBreak("") + xml;
- }
- }
- }
-
- return xml;
- };
-
- // Add indenting to data for pretty printing
- var addIndent = function(data, level) {
- if (prettyPrinting) {
-
- var indent = "";
- for (var i = 0; i < level; i++) {
- indent += indentString;
- }
- data = indent + data;
- }
-
- return data;
- };
-
- // Add line break to data for pretty printing
- var addBreak = function(data) {
- return prettyPrinting ? data + "\n" : data;
- };
-
- // Convert anything into a valid XML string representation
- var toString = function(data, isAttribute) {
- // Recursive function used to handle nested functions
- var functionHelper = function(data) {
- if (Object.prototype.toString.call(data) === "[object Function]") {
- return functionHelper(data());
- }
- else {
- return data;
- }
- };
-
- // Convert map
- if (Object.prototype.toString.call(data) in convertMap) {
- data = convertMap[Object.prototype.toString.call(data)](data);
- }
- else if ("*" in convertMap) {
- data = convertMap["*"](data);
- }
- // Functions
- else if (Object.prototype.toString.call(data) === "[object Function]") {
- data = functionHelper(data());
- }
- // Empty objects
- else if (Object.prototype.toString.call(data) === "[object Object]" && Object.keys(data).length === 0) {
- data = "";
- }
-
- // Cast data to string
- if (typeof data !== "string") {
- data = (data === null || typeof data === "undefined") ? "" : data.toString();
- }
-
- // Output as CDATA instead of escaping if option set (and only if not an attribute value)
- if (useCDATA && !isAttribute) {
- data = "/gm, "]]]]>") + "]]>";
- }
- else {
- // Escape illegal XML characters
- data = data.replace(/&/gm, "&")
- .replace(//gm, ">")
- .replace(/"/gm, """)
- .replace(/'/gm, "'");
- }
-
- return data;
- };
-
- // Revert options back to their default settings
- var setOptionDefaults = function() {
- useCDATA = false;
- convertMap = {};
- xmlDeclaration = true;
- xmlVersion = "1.0";
- xmlEncoding = "UTF-8";
- attributeString = "@";
- valueString = "#";
- prettyPrinting = true;
- indentString = "\t";
- };
-})();
+/* jshint node:true */
+
+/**
+ * js2xmlparser
+ * Copyright © 2012 Michael Kourlas and other contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+(function () {
+ "use strict";
+
+ var xmlDeclaration = true;
+ var xmlVersion = "1.0";
+ var xmlEncoding = "UTF-8";
+ var attributeString = "@";
+ var aliasString = "=";
+ var valueString = "#";
+ var prettyPrinting = true;
+ var indentString = "\t";
+ var convertMap = {};
+ var useCDATA = false;
+
+ module.exports = function (root, data, options) {
+ return toXML(init(root, data, options));
+ };
+
+ // Initialization
+ var init = function (root, data, options) {
+ // Set option defaults
+ setOptionDefaults();
+
+ // Error checking for root element
+ if (typeof root !== "string") {
+ throw new Error("root element must be a string");
+ }
+ else if (root === "") {
+ throw new Error("root element cannot be empty");
+ }
+
+ // Error checking and variable initialization for options
+ if (typeof options === "object" && options !== null) {
+ if ("declaration" in options) {
+ if ("include" in options.declaration) {
+ if (typeof options.declaration.include === "boolean") {
+ xmlDeclaration = options.declaration.include;
+ }
+ else {
+ throw new Error("declaration.include option must be a boolean");
+ }
+ }
+
+ if ("encoding" in options.declaration) {
+ if (typeof options.declaration.encoding === "string" || options.declaration.encoding === null) {
+ xmlEncoding = options.declaration.encoding;
+ }
+ else {
+ throw new Error("declaration.encoding option must be a string or null");
+ }
+ }
+ }
+ if ("attributeString" in options) {
+ if (typeof options.attributeString === "string") {
+ attributeString = options.attributeString;
+ }
+ else {
+ throw new Error("attributeString option must be a string");
+ }
+ }
+ if ("valueString" in options) {
+ if (typeof options.valueString === "string") {
+ valueString = options.valueString;
+ }
+ else {
+ throw new Error("valueString option must be a string");
+ }
+ }
+ if ("aliasString" in options) {
+ if (typeof options.aliasString === "string") {
+ aliasString = options.aliasString;
+ }
+ else {
+ throw new Error("aliasString option must be a string");
+ }
+ }
+ if ("prettyPrinting" in options) {
+ if ("enabled" in options.prettyPrinting) {
+ if (typeof options.prettyPrinting.enabled === "boolean") {
+ prettyPrinting = options.prettyPrinting.enabled;
+ }
+ else {
+ throw new Error("prettyPrinting.enabled option must be a boolean");
+ }
+ }
+
+ if ("indentString" in options.prettyPrinting) {
+ if (typeof options.prettyPrinting.indentString === "string") {
+ indentString = options.prettyPrinting.indentString;
+ }
+ else {
+ throw new Error("prettyPrinting.indentString option must be a string");
+ }
+ }
+ }
+ if ("convertMap" in options) {
+ if (Object.prototype.toString.call(options.convertMap) === "[object Object]") {
+ convertMap = options.convertMap;
+ }
+ else {
+ throw new Error("convertMap option must be an object");
+ }
+ }
+ if ("useCDATA" in options) {
+ if (typeof options.useCDATA === "boolean") {
+ useCDATA = options.useCDATA;
+ }
+ else {
+ throw new Error("useCDATA option must be a boolean");
+ }
+ }
+ }
+
+ // Error checking and variable initialization for data
+ if (typeof data !== "string" && typeof data !== "object" && typeof data !== "number" &&
+ typeof data !== "boolean" && data !== null) {
+ throw new Error("data must be an object (excluding arrays) or a JSON string");
+ }
+
+ if (data === null) {
+ throw new Error("data must be an object (excluding arrays) or a JSON string");
+ }
+
+ if (Object.prototype.toString.call(data) === "[object Array]") {
+ throw new Error("data must be an object (excluding arrays) or a JSON string");
+ }
+
+ if (typeof data === "string") {
+ data = JSON.parse(data);
+ }
+
+ var tempData = {};
+ tempData[root] = data; // Add root element to object
+
+ return tempData;
+ };
+
+ // Convert object to XML
+ var toXML = function (object) {
+ // Initialize arguments, if necessary
+ var xml = arguments[1] || "";
+ var level = arguments[2] || 0;
+
+ var i = null;
+ var tempObject = {};
+
+ for (var property in object) {
+ if (object.hasOwnProperty(property)) {
+ // Element name cannot start with a number
+ var elementName = property;
+ if (/^\d/.test(property)) {
+ elementName = "_" + property;
+ }
+
+ // Skip alias string property
+ if (elementName === aliasString) {
+ continue;
+ }
+
+ // When alias string property is present, use as alias for element name
+ if (Object.prototype.toString.call(object[property]) === "[object Object]" &&
+ aliasString in object[property]) {
+ elementName = object[property][aliasString];
+ }
+
+ // Arrays
+ if (Object.prototype.toString.call(object[property]) === "[object Array]") {
+ // Create separate XML elements for each array element
+ for (i = 0; i < object[property].length; i++) {
+ tempObject = {};
+ tempObject[property] = object[property][i];
+
+ xml = toXML(tempObject, xml, level);
+ }
+ }
+ // JSON-type objects with properties
+ else if (Object.prototype.toString.call(object[property]) === "[object Object]") {
+ xml += addIndent("<" + elementName, level);
+
+ // Add attributes
+ var lengthExcludingAttributes = Object.keys(object[property]).length;
+ if (Object.prototype.toString.call(object[property][attributeString]) === "[object Object]") {
+ lengthExcludingAttributes -= 1;
+ for (var attribute in object[property][attributeString]) {
+ if (object[property][attributeString].hasOwnProperty(attribute)) {
+ xml += " " + attribute + "=\"" +
+ toString(object[property][attributeString][attribute], true) + "\"";
+ }
+ }
+ }
+ else if (typeof object[property][attributeString] !== "undefined") {
+ // Fix for the case where an object contains a single property with the attribute string as its
+ // name, but this property contains no attributes; in that case, lengthExcludingAttributes
+ // should be set to zero to ensure that the object is considered an empty object for the
+ // purposes of the following if statement.
+ lengthExcludingAttributes -= 1;
+ }
+
+ if (lengthExcludingAttributes === 0) { // Empty object
+ xml += addBreak("/>");
+ }
+ else if ((lengthExcludingAttributes === 1 ||
+ (lengthExcludingAttributes === 2 && aliasString in object[property])) &&
+ valueString in object[property]) { // Value string only
+ xml += addBreak(">" + toString(object[property][valueString], false) + "" + elementName +
+ ">");
+ }
+ else { // Object with properties
+ xml += addBreak(">");
+
+ // Create separate object for each property and pass to this function
+ for (var subProperty in object[property]) {
+ if (object[property].hasOwnProperty(subProperty) && subProperty !== attributeString &&
+ subProperty !== valueString) {
+ tempObject = {};
+ tempObject[subProperty] = object[property][subProperty];
+
+ xml = toXML(tempObject, xml, level + 1);
+ }
+ }
+
+ xml += addBreak(addIndent("" + elementName + ">", level));
+ }
+ }
+ // Everything else
+ else {
+ xml += addBreak(addIndent("<" + elementName + ">" + toString(object[property], false) + "" +
+ elementName + ">", level));
+ }
+ }
+ }
+
+ // Finalize XML at end of process
+ if (level === 0) {
+ // Strip trailing whitespace
+ xml = xml.replace(/\s+$/g, "");
+
+ // Add XML declaration
+ if (xmlDeclaration) {
+ if (xmlEncoding === null) {
+ xml = addBreak("") + xml;
+ }
+ else {
+ xml = addBreak("") + xml;
+ }
+ }
+ }
+
+ return xml;
+ };
+
+ // Add indenting to data for pretty printing
+ var addIndent = function (data, level) {
+ if (prettyPrinting) {
+
+ var indent = "";
+ for (var i = 0; i < level; i++) {
+ indent += indentString;
+ }
+ data = indent + data;
+ }
+
+ return data;
+ };
+
+ // Add line break to data for pretty printing
+ var addBreak = function (data) {
+ return prettyPrinting ? data + "\n" : data;
+ };
+
+ // Convert anything into a valid XML string representation
+ var toString = function (data, isAttribute) {
+ // Recursive function used to handle nested functions
+ var functionHelper = function (data) {
+ if (Object.prototype.toString.call(data) === "[object Function]") {
+ return functionHelper(data());
+ }
+ else {
+ return data;
+ }
+ };
+
+ // Convert map
+ if (Object.prototype.toString.call(data) in convertMap) {
+ data = convertMap[Object.prototype.toString.call(data)](data);
+ }
+ else if ("*" in convertMap) {
+ data = convertMap["*"](data);
+ }
+ // Functions
+ else if (Object.prototype.toString.call(data) === "[object Function]") {
+ data = functionHelper(data());
+ }
+ // Empty objects
+ else if (Object.prototype.toString.call(data) === "[object Object]" && Object.keys(data).length === 0) {
+ data = "";
+ }
+
+ // Cast data to string
+ if (typeof data !== "string") {
+ data = (data === null || typeof data === "undefined") ? "" : data.toString();
+ }
+
+ // Output as CDATA instead of escaping if option set (and only if not an attribute value)
+ if (useCDATA && !isAttribute) {
+ data = "/gm, "]]]]>") + "]]>";
+ }
+ else {
+ // Escape illegal XML characters
+ data = data.replace(/&/gm, "&")
+ .replace(//gm, ">")
+ .replace(/"/gm, """)
+ .replace(/'/gm, "'");
+ }
+
+ return data;
+ };
+
+ // Revert options back to their default settings
+ var setOptionDefaults = function () {
+ useCDATA = false;
+ convertMap = {};
+ xmlDeclaration = true;
+ xmlVersion = "1.0";
+ xmlEncoding = "UTF-8";
+ attributeString = "@";
+ aliasString = "=";
+ valueString = "#";
+ prettyPrinting = true;
+ indentString = "\t";
+ };
+})();
diff --git a/node_modules/js2xmlparser/package.json b/node_modules/js2xmlparser/package.json
index a5a850fc..6204d6c4 100644
--- a/node_modules/js2xmlparser/package.json
+++ b/node_modules/js2xmlparser/package.json
@@ -13,7 +13,7 @@
"xml"
],
"homepage": "http://www.kourlas.net",
- "version": "0.1.5",
+ "version": "0.1.7",
"author": {
"name": "Michael Kourlas",
"email": "michael@kourlas.net"
@@ -28,27 +28,13 @@
"should": "*"
},
"license": "MIT",
+ "readme": "# js2xmlparser #\r\n\r\n## Overview ##\r\n\r\njs2xmlparser is a Node.js module that parses JavaScript objects into XML.\r\n\r\n## Features ##\r\n\r\nSince XML is a data-interchange format, js2xmlparser is designed primarily for JSON-type objects, arrays and primitive\r\ndata types, like many of the other JavaScript to XML parsers currently available for Node.js.\r\n\r\nHowever, js2xmlparser is capable of parsing any object, including native JavaScript objects such as Date and RegExp, by\r\ntaking advantage of each object's toString function. Functions are a special case where the return value of the function\r\nitself is used instead of the toString function, if available.\r\n\r\njs2xmlparser also supports a number of constructs unique to XML:\r\n\r\n* attributes (through a unique attribute property in objects)\r\n* mixed content (through a unique value property in objects)\r\n* multiple elements with the same name (through arrays)\r\n\r\njs2xmlparser can also pretty-print the XML it outputs with the option of customizing the indent string.\r\n\r\n## Installation ##\r\n\r\nThe easiest way to install js2xmlparser is to use npm: `npm install js2xmlparser`.\r\n\r\nAlternatively, you may download the source from GitHub and copy it to a folder named \"js2xmlparser\" within your\r\n\"node_modules\" directory.\r\n\r\n## Usage ##\r\n\r\nThe js2xmlparser module contains one function which takes the following arguments:\r\n\r\n* `root` - the XML root element's name (string, mandatory)\r\n* `data` - the data to be converted to XML; while the data object can contain arrays, it cannot itself be an array\r\n (object or JSON string, mandatory)\r\n* `options` - module options (object, optional)\r\n * `declaration` - XML declaration options (object, optional)\r\n * `include` - specifies whether an XML declaration should be included (boolean, optional, default: true)\r\n * `encoding` - value of XML encoding attribute in declaration; a value of null represents no encoding attribute\r\n (string, optional, default: \"UTF-8\")\r\n * `attributeString` - the name of the property representing an element's attributes; note that any property with a\r\n name equal to the attribute string is ignored except in the context of XML attributes (string, optional, default:\r\n \"@\")\r\n * `valueString` - the name of the property representing an element's value; note that any property with a name equal\r\n to the value string is ignored except in the context of supplying a value for a tag containing attributes (string,\r\n optional, default: \"#\")\r\n * `aliasString` - the name of the property representing an element's alias; the name of the containing element will\r\n be replaced with the alias (string, optional, default: \"=\")\r\n * `prettyPrinting` - pretty-printing options (object, optional)\r\n * `enabled` - specifies whether pretty-printing is enabled (boolean, optional, default: true)\r\n * `indentString` - indent string (string, optional, default: \"\\t\")\r\n * `convertMap` - maps object types (as given by the `Object.prototype.toString.call` method) to functions to convert\r\n those objects to a particular string representation; `*` can be used as a wildcard for all types of objects\r\n (object, optional, default: {})\r\n * `useCDATA` - specifies whether strings should be enclosed in CDATA tags; otherwise, illegal XML characters will\r\n be escaped (boolean, optional, default: false)\r\n\r\n## Examples ##\r\n\r\nThe following example illustrates the basic usage of js2xmlparser:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\"\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > \r\n > \r\n > John\r\n > Smith\r\n > \r\n\r\nThis is a more complex example that builds on the first:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"@\": {\r\n \"type\": \"individual\"\r\n },\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\",\r\n \"dateOfBirth\": new Date(1964, 7, 26),\r\n \"address\": {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"streetAddress\": \"3212 22nd St\",\r\n \"city\": \"Chicago\",\r\n \"state\": \"Illinois\",\r\n \"zip\": 10000\r\n },\r\n \"phone\": [\r\n {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"#\": \"123-555-4567\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"work\"\r\n },\r\n \"#\": \"123-555-4567\",\r\n \"=\": \"telephone\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"cell\"\r\n },\r\n \"#\": \"456-555-7890\"\r\n }\r\n ],\r\n \"email\": function() {return \"john@smith.com\";},\r\n \"notes\": \"John's profile is not complete.\"\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > \r\n > \r\n > John\r\n > Smith\r\n > Wed Aug 26 1964 00:00:00 GMT-0400 (Eastern Daylight Time)\r\n > \r\n > 3212 22nd St\r\n > Chicago\r\n > Illinois\r\n > 10000\r\n > \r\n > 123-555-4567\r\n > 123-555-4567\r\n > 456-555-7890\r\n > john@smith.com\r\n > John's profile is not complete.\r\n > \r\n\r\nThis example uses the alias string feature:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"phone\": [\r\n {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"#\": \"123-555-4567\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"work\"\r\n },\r\n \"#\": \"123-555-4567\",\r\n \"=\": \"telephone\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"cell\"\r\n },\r\n \"#\": \"456-555-7890\"\r\n }\r\n ]\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > \r\n > \r\n > \t123-555-4567\r\n > \t123-555-4567\r\n > \t456-555-7890\r\n > \r\n\r\nThe following an example that uses the convert map feature:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"email\": function() {return \"john@smith.com\";},\r\n \"dateOfBirth\": new Date(1964, 7, 26)\r\n }\r\n\r\n var options = {\r\n convertMap: {\r\n \"[object Date]\": function(date) {\r\n return date.toISOString();\r\n },\r\n \"[object Function]\": function(func) {\r\n return func.toString();\r\n }\r\n }\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data, options));\r\n\r\n > \r\n > \r\n > function () {return "john@smith.com";}\r\n > 1964-08-26T04:00:00.000Z\r\n > \r\n\r\nHere's an example that wraps strings in CDATA tags instead of escaping invalid characters:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"notes\": {\r\n \"@\": {\r\n \"type\": \"status\"\r\n },\r\n \"#\": \"John's profile is not complete.\"\r\n }\r\n };\r\n\r\n var options = {\r\n useCDATA: true\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data, options));\r\n\r\n > \r\n > \r\n > \r\n > \r\n\r\n## Tests ##\r\n\r\njs2xmlparser comes with a set of tests that evaluate and verify the package's core functionality. To run the tests:\r\n\r\n* Install the test dependencies with `npm install`.\r\n* Run the tests with `mocha`.\r\n\r\n## License ##\r\n\r\njs2xmlparser is licensed under the [MIT license](http://opensource.org/licenses/MIT). Please see the LICENSE.md file\r\nfor more information.\r\n",
+ "readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/michaelkourlas/node-js2xmlparser/issues"
},
- "_id": "js2xmlparser@0.1.5",
- "_shasum": "b42b3ac5a74bb282ff06cc93dfa67fb98a22959d",
- "_from": "js2xmlparser@0.1.5",
- "_npmVersion": "1.4.9",
- "_npmUser": {
- "name": "michaelkourlas",
- "email": "michael@kourlas.net"
- },
- "maintainers": [
- {
- "name": "michaelkourlas",
- "email": "michaelkourlas@gmail.com"
- }
- ],
- "dist": {
- "shasum": "b42b3ac5a74bb282ff06cc93dfa67fb98a22959d",
- "tarball": "http://registry.npmjs.org/js2xmlparser/-/js2xmlparser-0.1.5.tgz"
- },
- "directories": {},
- "_resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-0.1.5.tgz"
+ "_id": "js2xmlparser@0.1.7",
+ "_shasum": "c8a4bf9ba00577c4b2ce0bd6e714ee8341a586ae",
+ "_from": "js2xmlparser@~0.1.7",
+ "_resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-0.1.7.tgz"
}
diff --git a/node_modules/marked/package.json b/node_modules/marked/package.json
index bbea5341..baa0adb4 100644
--- a/node_modules/marked/package.json
+++ b/node_modules/marked/package.json
@@ -45,6 +45,6 @@
"readmeFilename": "README.md",
"_id": "marked@0.3.2",
"_shasum": "015db158864438f24a64bdd61a0428b418706d09",
- "_from": "marked@0.3.2",
+ "_from": "marked@~0.3.2",
"_resolved": "https://registry.npmjs.org/marked/-/marked-0.3.2.tgz"
}
diff --git a/node_modules/strip-json-comments/package.json b/node_modules/strip-json-comments/package.json
index c55dc5f2..1361a6fd 100644
--- a/node_modules/strip-json-comments/package.json
+++ b/node_modules/strip-json-comments/package.json
@@ -1,6 +1,6 @@
{
"name": "strip-json-comments",
- "version": "0.1.3",
+ "version": "1.0.2",
"description": "Strip comments from JSON. Lets you use comments in your JSON files!",
"keywords": [
"json",
@@ -37,7 +37,7 @@
},
"repository": {
"type": "git",
- "url": "git://github.com/sindresorhus/strip-json-comments"
+ "url": "https://github.com/sindresorhus/strip-json-comments"
},
"scripts": {
"test": "mocha"
@@ -48,14 +48,31 @@
"engines": {
"node": ">=0.8.0"
},
- "readme": "# strip-json-comments [](https://travis-ci.org/sindresorhus/strip-json-comments)\n\n> Strip comments from JSON. Lets you use comments in your JSON files!\n\nThis is now possible:\n\n```js\n{\n\t// rainbows\n\t\"unicorn\": /* ❤ */ \"cake\"\n}\n```\n\nIt will remove single-line comments `//` and mult-line comments `/**/`.\n\nAlso available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin and a [require hook](https://github.com/uTest/autostrip-json-comments).\n\n\n*There's already [json-comments](https://npmjs.org/package/json-comments), but it's only for Node.js and uses a naive regex to strip comments which fails on simple cases like `{\"a\":\"//\"}`. This module however parses out the comments.*\n\n\n## Install\n\n```sh\n$ npm install --save strip-json-comments\n```\n\n```sh\n$ bower install --save strip-json-comments\n```\n\n```sh\n$ component install sindresorhus/strip-json-comments\n```\n\n\n## Usage\n\n```js\nvar json = '{/*rainbows*/\"unicorn\":\"cake\"}';\nJSON.parse(stripJsonComments(json));\n//=> {unicorn: 'cake'}\n```\n\n\n## API\n\n### stripJsonComments(input)\n\n#### input\n\nType: `string`\n\nAccepts a string with JSON and returns a string without comments.\n\n\n## CLI\n\n```sh\n$ npm install --global strip-json-comments\n```\n\n```sh\n$ strip-json-comments --help\n\nstrip-json-comments > \n# or\ncat | strip-json-comments > \n```\n\n\n## License\n\nMIT © [Sindre Sorhus](http://sindresorhus.com)\n",
- "readmeFilename": "readme.md",
+ "gitHead": "142dd671c71f90fb7fdba440184b1bb64543acb3",
"bugs": {
"url": "https://github.com/sindresorhus/strip-json-comments/issues"
},
"homepage": "https://github.com/sindresorhus/strip-json-comments",
- "_id": "strip-json-comments@0.1.3",
- "_shasum": "164c64e370a8a3cc00c9e01b539e569823f0ee54",
- "_from": "strip-json-comments@0.1.3",
- "_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz"
+ "_id": "strip-json-comments@1.0.2",
+ "_shasum": "5a48ab96023dbac1b7b8d0ffabf6f63f1677be9f",
+ "_from": "strip-json-comments@~1.0.2",
+ "_npmVersion": "2.1.2",
+ "_nodeVersion": "0.10.32",
+ "_npmUser": {
+ "name": "sindresorhus",
+ "email": "sindresorhus@gmail.com"
+ },
+ "maintainers": [
+ {
+ "name": "sindresorhus",
+ "email": "sindresorhus@gmail.com"
+ }
+ ],
+ "dist": {
+ "shasum": "5a48ab96023dbac1b7b8d0ffabf6f63f1677be9f",
+ "tarball": "http://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz",
+ "readme": "ERROR: No README data found!"
}
diff --git a/node_modules/strip-json-comments/strip-json-comments.js b/node_modules/strip-json-comments/strip-json-comments.js
index 2e7fdef2..a47976fd 100644
--- a/node_modules/strip-json-comments/strip-json-comments.js
+++ b/node_modules/strip-json-comments/strip-json-comments.js
@@ -34,6 +34,9 @@
} else if (insideComment === 'single' && currentChar + nextChar === '\r\n') {
insideComment = false;
i++;
+ ret += currentChar;
+ ret += nextChar;
+ continue;
} else if (insideComment === 'single' && currentChar === '\n') {
insideComment = false;
} else if (!insideComment && currentChar + nextChar === '/*') {
diff --git a/node_modules/taffydb/package.json b/node_modules/taffydb/package.json
index 1165f201..98bd017f 100644
--- a/node_modules/taffydb/package.json
+++ b/node_modules/taffydb/package.json
@@ -16,6 +16,6 @@
"homepage": "https://github.com/hegemonic/taffydb",
"_id": "taffydb@2.6.2",
"_shasum": "3c549d2f5712d7d1d109ad6bb1a4084f1b7add4e",
- "_from": "https://github.com/hegemonic/taffydb/tarball/master",
- "_resolved": "https://github.com/hegemonic/taffydb/tarball/master"
+ "_from": "https://github.com/hegemonic/taffydb/tarball/7d100bcee0e997ee4977e273cdce60bd8933050e",
+ "_resolved": "https://github.com/hegemonic/taffydb/tarball/7d100bcee0e997ee4977e273cdce60bd8933050e"
}
diff --git a/node_modules/underscore/package.json b/node_modules/underscore/package.json
index d561286b..5a82a144 100644
--- a/node_modules/underscore/package.json
+++ b/node_modules/underscore/package.json
@@ -18,14 +18,15 @@
"url": "git://github.com/jashkenas/underscore.git"
},
"main": "underscore.js",
- "version": "1.6.0",
+ "version": "1.7.0",
"devDependencies": {
"docco": "0.6.x",
- "phantomjs": "1.9.0-1",
- "uglify-js": "2.4.x"
+ "phantomjs": "1.9.7-1",
+ "uglify-js": "2.4.x",
+ "eslint": "0.6.x"
},
"scripts": {
- "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true",
+ "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true && eslint underscore.js test/*.js test/vendor/runner.js",
"build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js",
"doc": "docco underscore.js"
},
@@ -40,13 +41,29 @@
"underscore-min.js",
"LICENSE"
],
- "readme": " __\n /\\ \\ __\n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____\n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\\n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n \\ \\____/\n \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nUnderscore is an open-sourced component of DocumentCloud:\nhttps://github.com/documentcloud\n\nMany thanks to our contributors:\nhttps://github.com/jashkenas/underscore/contributors\n",
- "readmeFilename": "README.md",
+ "gitHead": "da996e665deb0b69b257e80e3e257c04fde4191c",
"bugs": {
"url": "https://github.com/jashkenas/underscore/issues"
},
- "_id": "underscore@1.6.0",
- "_shasum": "8b38b10cacdef63337b8b24e4ff86d45aea529a8",
- "_from": "underscore@1.6.0",
- "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
+ "_id": "underscore@1.7.0",
+ "_shasum": "6bbaf0877500d36be34ecaa584e0db9fef035209",
+ "_from": "underscore@~1.7.0",
+ "_npmVersion": "1.4.24",
+ "_npmUser": {
+ "name": "jashkenas",
+ "email": "jashkenas@gmail.com"
+ },
+ "maintainers": [
+ {
+ "name": "jashkenas",
+ "email": "jashkenas@gmail.com"
+ }
+ ],
+ "dist": {
+ "shasum": "6bbaf0877500d36be34ecaa584e0db9fef035209",
+ "tarball": "http://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
+ "readme": "ERROR: No README data found!"
}
diff --git a/node_modules/underscore/underscore.js b/node_modules/underscore/underscore.js
index 9a4cabec..b4f49a02 100644
--- a/node_modules/underscore/underscore.js
+++ b/node_modules/underscore/underscore.js
@@ -1,4 +1,4 @@
-// Underscore.js 1.6.0
+// Underscore.js 1.7.0
// http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
@@ -14,9 +14,6 @@
// Save the previous value of the `_` variable.
var previousUnderscore = root._;
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
@@ -31,15 +28,6 @@
// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind;
@@ -53,8 +41,7 @@
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode.
+ // the browser, add `_` as a global object.
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
@@ -65,98 +52,125 @@
}
// Current version.
- _.VERSION = '1.6.0';
+ _.VERSION = '1.7.0';
+
+ // Internal function that returns an efficient (for current engines) version
+ // of the passed-in callback, to be repeatedly applied in other Underscore
+ // functions.
+ var createCallback = function(func, context, argCount) {
+ if (context === void 0) return func;
+ switch (argCount == null ? 3 : argCount) {
+ case 1: return function(value) {
+ return func.call(context, value);
+ };
+ case 2: return function(value, other) {
+ return func.call(context, value, other);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(context, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(context, accumulator, value, index, collection);
+ };
+ }
+ return function() {
+ return func.apply(context, arguments);
+ };
+ };
+
+ // A mostly-internal function to generate callbacks that can be applied
+ // to each element in a collection, returning the desired result — either
+ // identity, an arbitrary callback, a property matcher, or a property accessor.
+ _.iteratee = function(value, context, argCount) {
+ if (value == null) return _.identity;
+ if (_.isFunction(value)) return createCallback(value, context, argCount);
+ if (_.isObject(value)) return _.matches(value);
+ return _.property(value);
+ };
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
+ // Handles raw objects in addition to array-likes. Treats all
+ // sparse array-likes as if they were dense.
+ _.each = _.forEach = function(obj, iteratee, context) {
if (obj == null) return obj;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, length = obj.length; i < length; i++) {
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
+ iteratee = createCallback(iteratee, context);
+ var i, length = obj.length;
+ if (length === +length) {
+ for (i = 0; i < length; i++) {
+ iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
- for (var i = 0, length = keys.length; i < length; i++) {
- if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
+ for (i = 0, length = keys.length; i < length; i++) {
+ iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results.push(iterator.call(context, value, index, list));
- });
+ // Return the results of applying the iteratee to each element.
+ _.map = _.collect = function(obj, iteratee, context) {
+ if (obj == null) return [];
+ iteratee = _.iteratee(iteratee, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ results = Array(length),
+ currentKey;
+ for (var index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ results[index] = iteratee(obj[currentKey], currentKey, obj);
+ }
return results;
};
var reduceError = 'Reduce of empty array with no initial value';
// **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
+ // or `foldl`.
+ _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ iteratee = createCallback(iteratee, context, 4);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index = 0, currentKey;
+ if (arguments.length < 3) {
+ if (!length) throw new TypeError(reduceError);
+ memo = obj[keys ? keys[index++] : index++];
+ }
+ for (; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
return memo;
};
// The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
+ _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ iteratee = createCallback(iteratee, context, 4);
+ var keys = obj.length !== + obj.length && _.keys(obj),
+ index = (keys || obj).length,
+ currentKey;
+ if (arguments.length < 3) {
+ if (!index) throw new TypeError(reduceError);
+ memo = obj[keys ? keys[--index] : --index];
}
- var length = obj.length;
- if (length !== +length) {
- var keys = _.keys(obj);
- length = keys.length;
+ while (index--) {
+ currentKey = keys ? keys[index] : index;
+ memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
- each(obj, function(value, index, list) {
- index = keys ? keys[--length] : --length;
- if (!initial) {
- memo = obj[index];
- initial = true;
- } else {
- memo = iterator.call(context, memo, obj[index], index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
return memo;
};
// Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) {
var result;
- any(obj, function(value, index, list) {
- if (predicate.call(context, value, index, list)) {
+ predicate = _.iteratee(predicate, context);
+ _.some(obj, function(value, index, list) {
+ if (predicate(value, index, list)) {
result = value;
return true;
}
@@ -165,61 +179,58 @@
};
// Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) {
var results = [];
if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
- each(obj, function(value, index, list) {
- if (predicate.call(context, value, index, list)) results.push(value);
+ predicate = _.iteratee(predicate, context);
+ _.each(obj, function(value, index, list) {
+ if (predicate(value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) {
- return _.filter(obj, function(value, index, list) {
- return !predicate.call(context, value, index, list);
- }, context);
+ return _.filter(obj, _.negate(_.iteratee(predicate)), context);
};
// Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
_.every = _.all = function(obj, predicate, context) {
- predicate || (predicate = _.identity);
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
- each(obj, function(value, index, list) {
- if (!(result = result && predicate.call(context, value, index, list))) return breaker;
- });
- return !!result;
+ if (obj == null) return true;
+ predicate = _.iteratee(predicate, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index, currentKey;
+ for (index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ if (!predicate(obj[currentKey], currentKey, obj)) return false;
+ }
+ return true;
};
// Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`.
- var any = _.some = _.any = function(obj, predicate, context) {
- predicate || (predicate = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
- each(obj, function(value, index, list) {
- if (result || (result = predicate.call(context, value, index, list))) return breaker;
- });
- return !!result;
+ _.some = _.any = function(obj, predicate, context) {
+ if (obj == null) return false;
+ predicate = _.iteratee(predicate, context);
+ var keys = obj.length !== +obj.length && _.keys(obj),
+ length = (keys || obj).length,
+ index, currentKey;
+ for (index = 0; index < length; index++) {
+ currentKey = keys ? keys[index] : index;
+ if (predicate(obj[currentKey], currentKey, obj)) return true;
+ }
+ return false;
};
// Determine if the array or object contains a given value (using `===`).
// Aliased as `include`.
_.contains = _.include = function(obj, target) {
if (obj == null) return false;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- return any(obj, function(value) {
- return value === target;
- });
+ if (obj.length !== +obj.length) obj = _.values(obj);
+ return _.indexOf(obj, target) >= 0;
};
// Invoke a method (with arguments) on every item in a collection.
@@ -248,51 +259,67 @@
return _.find(obj, _.matches(attrs));
};
- // Return the maximum element or (element-based computation).
- // Can't optimize arrays of integers longer than 65,535 elements.
- // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.max.apply(Math, obj);
- }
- var result = -Infinity, lastComputed = -Infinity;
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- if (computed > lastComputed) {
- result = value;
- lastComputed = computed;
+ // Return the maximum element (or element-based computation).
+ _.max = function(obj, iteratee, context) {
+ var result = -Infinity, lastComputed = -Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = obj.length === +obj.length ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value > result) {
+ result = value;
+ }
}
- });
+ } else {
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
return result;
};
// Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.min.apply(Math, obj);
- }
- var result = Infinity, lastComputed = Infinity;
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- if (computed < lastComputed) {
- result = value;
- lastComputed = computed;
+ _.min = function(obj, iteratee, context) {
+ var result = Infinity, lastComputed = Infinity,
+ value, computed;
+ if (iteratee == null && obj != null) {
+ obj = obj.length === +obj.length ? obj : _.values(obj);
+ for (var i = 0, length = obj.length; i < length; i++) {
+ value = obj[i];
+ if (value < result) {
+ result = value;
+ }
}
- });
+ } else {
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index, list) {
+ computed = iteratee(value, index, list);
+ if (computed < lastComputed || computed === Infinity && result === Infinity) {
+ result = value;
+ lastComputed = computed;
+ }
+ });
+ }
return result;
};
- // Shuffle an array, using the modern version of the
+ // Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) {
- var rand;
- var index = 0;
- var shuffled = [];
- each(obj, function(value) {
- rand = _.random(index++);
- shuffled[index - 1] = shuffled[rand];
- shuffled[rand] = value;
- });
+ var set = obj && obj.length === +obj.length ? obj : _.values(obj);
+ var length = set.length;
+ var shuffled = Array(length);
+ for (var index = 0, rand; index < length; index++) {
+ rand = _.random(0, index);
+ if (rand !== index) shuffled[index] = shuffled[rand];
+ shuffled[rand] = set[index];
+ }
return shuffled;
};
@@ -307,21 +334,14 @@
return _.shuffle(obj).slice(0, Math.max(0, n));
};
- // An internal function to generate lookup iterators.
- var lookupIterator = function(value) {
- if (value == null) return _.identity;
- if (_.isFunction(value)) return value;
- return _.property(value);
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, iterator, context) {
- iterator = lookupIterator(iterator);
+ // Sort the object's values by a criterion produced by an iteratee.
+ _.sortBy = function(obj, iteratee, context) {
+ iteratee = _.iteratee(iteratee, context);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
index: index,
- criteria: iterator.call(context, value, index, list)
+ criteria: iteratee(value, index, list)
};
}).sort(function(left, right) {
var a = left.criteria;
@@ -336,12 +356,12 @@
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
- return function(obj, iterator, context) {
+ return function(obj, iteratee, context) {
var result = {};
- iterator = lookupIterator(iterator);
- each(obj, function(value, index) {
- var key = iterator.call(context, value, index, obj);
- behavior(result, key, value);
+ iteratee = _.iteratee(iteratee, context);
+ _.each(obj, function(value, index) {
+ var key = iteratee(value, index, obj);
+ behavior(result, value, key);
});
return result;
};
@@ -349,32 +369,32 @@
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
- _.groupBy = group(function(result, key, value) {
- _.has(result, key) ? result[key].push(value) : result[key] = [value];
+ _.groupBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key].push(value); else result[key] = [value];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
- _.indexBy = group(function(result, key, value) {
+ _.indexBy = group(function(result, value, key) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
- _.countBy = group(function(result, key) {
- _.has(result, key) ? result[key]++ : result[key] = 1;
+ _.countBy = group(function(result, value, key) {
+ if (_.has(result, key)) result[key]++; else result[key] = 1;
});
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator, context) {
- iterator = lookupIterator(iterator);
- var value = iterator.call(context, obj);
+ _.sortedIndex = function(array, obj, iteratee, context) {
+ iteratee = _.iteratee(iteratee, context, 1);
+ var value = iteratee(obj);
var low = 0, high = array.length;
while (low < high) {
- var mid = (low + high) >>> 1;
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+ var mid = low + high >>> 1;
+ if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
@@ -390,7 +410,18 @@
// Return the number of elements in an object.
_.size = function(obj) {
if (obj == null) return 0;
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+ return obj.length === +obj.length ? obj.length : _.keys(obj).length;
+ };
+
+ // Split a collection into two arrays: one whose elements all satisfy the given
+ // predicate, and one whose elements all do not satisfy the predicate.
+ _.partition = function(obj, predicate, context) {
+ predicate = _.iteratee(predicate, context);
+ var pass = [], fail = [];
+ _.each(obj, function(value, key, obj) {
+ (predicate(value, key, obj) ? pass : fail).push(value);
+ });
+ return [pass, fail];
};
// Array Functions
@@ -401,7 +432,7 @@
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0;
- if ((n == null) || guard) return array[0];
+ if (n == null || guard) return array[0];
if (n < 0) return [];
return slice.call(array, 0, n);
};
@@ -411,14 +442,14 @@
// the array, excluding the last N. The **guard** check allows it to work with
// `_.map`.
_.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
};
// Get the last element of an array. Passing **n** will return the last N
// values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) {
if (array == null) return void 0;
- if ((n == null) || guard) return array[array.length - 1];
+ if (n == null || guard) return array[array.length - 1];
return slice.call(array, Math.max(array.length - n, 0));
};
@@ -427,7 +458,7 @@
// the rest N values in the array. The **guard**
// check allows it to work with `_.map`.
_.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, (n == null) || guard ? 1 : n);
+ return slice.call(array, n == null || guard ? 1 : n);
};
// Trim out all falsy values from an array.
@@ -436,23 +467,26 @@
};
// Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, output) {
+ var flatten = function(input, shallow, strict, output) {
if (shallow && _.every(input, _.isArray)) {
return concat.apply(output, input);
}
- each(input, function(value) {
- if (_.isArray(value) || _.isArguments(value)) {
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
+ for (var i = 0, length = input.length; i < length; i++) {
+ var value = input[i];
+ if (!_.isArray(value) && !_.isArguments(value)) {
+ if (!strict) output.push(value);
+ } else if (shallow) {
+ push.apply(output, value);
} else {
- output.push(value);
+ flatten(value, shallow, strict, output);
}
- });
+ }
return output;
};
// Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) {
- return flatten(array, shallow, []);
+ return flatten(array, shallow, false, []);
};
// Return a version of the array that does not contain the specified value(s).
@@ -460,68 +494,77 @@
return _.difference(array, slice.call(arguments, 1));
};
- // Split an array into two arrays: one whose elements all satisfy the given
- // predicate, and one whose elements all do not satisfy the predicate.
- _.partition = function(array, predicate) {
- var pass = [], fail = [];
- each(array, function(elem) {
- (predicate(elem) ? pass : fail).push(elem);
- });
- return [pass, fail];
- };
-
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
- if (_.isFunction(isSorted)) {
- context = iterator;
- iterator = isSorted;
+ _.uniq = _.unique = function(array, isSorted, iteratee, context) {
+ if (array == null) return [];
+ if (!_.isBoolean(isSorted)) {
+ context = iteratee;
+ iteratee = isSorted;
isSorted = false;
}
- var initial = iterator ? _.map(array, iterator, context) : array;
- var results = [];
+ if (iteratee != null) iteratee = _.iteratee(iteratee, context);
+ var result = [];
var seen = [];
- each(initial, function(value, index) {
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
- seen.push(value);
- results.push(array[index]);
+ for (var i = 0, length = array.length; i < length; i++) {
+ var value = array[i];
+ if (isSorted) {
+ if (!i || seen !== value) result.push(value);
+ seen = value;
+ } else if (iteratee) {
+ var computed = iteratee(value, i, array);
+ if (_.indexOf(seen, computed) < 0) {
+ seen.push(computed);
+ result.push(value);
+ }
+ } else if (_.indexOf(result, value) < 0) {
+ result.push(value);
}
- });
- return results;
+ }
+ return result;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_.union = function() {
- return _.uniq(_.flatten(arguments, true));
+ return _.uniq(flatten(arguments, true, true, []));
};
// Produce an array that contains every item shared between all the
// passed-in arrays.
_.intersection = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.contains(other, item);
- });
- });
+ if (array == null) return [];
+ var result = [];
+ var argsLength = arguments.length;
+ for (var i = 0, length = array.length; i < length; i++) {
+ var item = array[i];
+ if (_.contains(result, item)) continue;
+ for (var j = 1; j < argsLength; j++) {
+ if (!_.contains(arguments[j], item)) break;
+ }
+ if (j === argsLength) result.push(item);
+ }
+ return result;
};
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_.difference = function(array) {
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
- return _.filter(array, function(value){ return !_.contains(rest, value); });
+ var rest = flatten(slice.call(arguments, 1), true, true, []);
+ return _.filter(array, function(value){
+ return !_.contains(rest, value);
+ });
};
// Zip together multiple lists into a single array -- elements that share
// an index go together.
- _.zip = function() {
- var length = _.max(_.pluck(arguments, 'length').concat(0));
- var results = new Array(length);
+ _.zip = function(array) {
+ if (array == null) return [];
+ var length = _.max(arguments, 'length').length;
+ var results = Array(length);
for (var i = 0; i < length; i++) {
- results[i] = _.pluck(arguments, '' + i);
+ results[i] = _.pluck(arguments, i);
}
return results;
};
@@ -542,10 +585,8 @@
return result;
};
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // Return the position of the first occurrence of an item in an array,
+ // or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) {
@@ -553,26 +594,23 @@
var i = 0, length = array.length;
if (isSorted) {
if (typeof isSorted == 'number') {
- i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
+ i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
} else {
i = _.sortedIndex(array, item);
return array[i] === item ? i : -1;
}
}
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i;
return -1;
};
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
_.lastIndexOf = function(array, item, from) {
if (array == null) return -1;
- var hasIndex = from != null;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+ var idx = array.length;
+ if (typeof from == 'number') {
+ idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
}
- var i = (hasIndex ? from : array.length);
- while (i--) if (array[i] === item) return i;
+ while (--idx >= 0) if (array[idx] === item) return idx;
return -1;
};
@@ -584,15 +622,13 @@
stop = start || 0;
start = 0;
}
- step = arguments[2] || 1;
+ step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(length);
+ var range = Array(length);
- while(idx < length) {
- range[idx++] = start;
- start += step;
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
}
return range;
@@ -602,7 +638,7 @@
// ------------------
// Reusable constructor function for prototype setting.
- var ctor = function(){};
+ var Ctor = function(){};
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
@@ -610,17 +646,18 @@
_.bind = function(func, context) {
var args, bound;
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- if (!_.isFunction(func)) throw new TypeError;
+ if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
args = slice.call(arguments, 2);
- return bound = function() {
+ bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
- ctor.prototype = func.prototype;
- var self = new ctor;
- ctor.prototype = null;
+ Ctor.prototype = func.prototype;
+ var self = new Ctor;
+ Ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments)));
- if (Object(result) === result) return result;
+ if (_.isObject(result)) return result;
return self;
};
+ return bound;
};
// Partially apply a function by creating a version that has had some of its
@@ -643,27 +680,34 @@
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length === 0) throw new Error('bindAll must be passed function names');
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ var i, length = arguments.length, key;
+ if (length <= 1) throw new Error('bindAll must be passed function names');
+ for (i = 1; i < length; i++) {
+ key = arguments[i];
+ obj[key] = _.bind(obj[key], obj);
+ }
return obj;
};
// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ var memoize = function(key) {
+ var cache = memoize.cache;
+ var address = hasher ? hasher.apply(this, arguments) : key;
+ if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
+ return cache[address];
};
+ memoize.cache = {};
+ return memoize;
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
+ return setTimeout(function(){
+ return func.apply(null, args);
+ }, wait);
};
// Defers a function, scheduling it to run after the current call stack has
@@ -681,12 +725,12 @@
var context, args, result;
var timeout = null;
var previous = 0;
- options || (options = {});
+ if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
- context = args = null;
+ if (!timeout) context = args = null;
};
return function() {
var now = _.now();
@@ -694,12 +738,12 @@
var remaining = wait - (now - previous);
context = this;
args = arguments;
- if (remaining <= 0) {
+ if (remaining <= 0 || remaining > wait) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
- context = args = null;
+ if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
@@ -716,13 +760,14 @@
var later = function() {
var last = _.now() - timestamp;
- if (last < wait) {
+
+ if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
- context = args = null;
+ if (!timeout) context = args = null;
}
}
};
@@ -732,9 +777,7 @@
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
- if (!timeout) {
- timeout = setTimeout(later, wait);
- }
+ if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
@@ -744,19 +787,6 @@
};
};
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
- };
- };
-
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
@@ -764,16 +794,23 @@
return _.partial(wrapper, func);
};
+ // Returns a negated version of the passed-in predicate.
+ _.negate = function(predicate) {
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ };
+
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function() {
- var funcs = arguments;
+ var args = arguments;
+ var start = args.length - 1;
return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
+ var i = start;
+ var result = args[start].apply(this, arguments);
+ while (i--) result = args[i].call(this, result);
+ return result;
};
};
@@ -786,6 +823,23 @@
};
};
+ // Returns a function that will only be executed before being called N times.
+ _.before = function(times, func) {
+ var memo;
+ return function() {
+ if (--times > 0) {
+ memo = func.apply(this, arguments);
+ } else {
+ func = null;
+ }
+ return memo;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = _.partial(_.before, 2);
+
// Object Functions
// ----------------
@@ -803,7 +857,7 @@
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
- var values = new Array(length);
+ var values = Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
@@ -814,7 +868,7 @@
_.pairs = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
- var pairs = new Array(length);
+ var pairs = Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
@@ -843,45 +897,62 @@
// Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- obj[prop] = source[prop];
+ if (!_.isObject(obj)) return obj;
+ var source, prop;
+ for (var i = 1, length = arguments.length; i < length; i++) {
+ source = arguments[i];
+ for (prop in source) {
+ if (hasOwnProperty.call(source, prop)) {
+ obj[prop] = source[prop];
}
}
- });
+ }
return obj;
};
// Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- each(keys, function(key) {
- if (key in obj) copy[key] = obj[key];
- });
- return copy;
+ _.pick = function(obj, iteratee, context) {
+ var result = {}, key;
+ if (obj == null) return result;
+ if (_.isFunction(iteratee)) {
+ iteratee = createCallback(iteratee, context);
+ for (key in obj) {
+ var value = obj[key];
+ if (iteratee(value, key, obj)) result[key] = value;
+ }
+ } else {
+ var keys = concat.apply([], slice.call(arguments, 1));
+ obj = new Object(obj);
+ for (var i = 0, length = keys.length; i < length; i++) {
+ key = keys[i];
+ if (key in obj) result[key] = obj[key];
+ }
+ }
+ return result;
};
// Return a copy of the object without the blacklisted properties.
- _.omit = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- for (var key in obj) {
- if (!_.contains(keys, key)) copy[key] = obj[key];
+ _.omit = function(obj, iteratee, context) {
+ if (_.isFunction(iteratee)) {
+ iteratee = _.negate(iteratee);
+ } else {
+ var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
+ iteratee = function(value, key) {
+ return !_.contains(keys, key);
+ };
}
- return copy;
+ return _.pick(obj, iteratee, context);
};
// Fill in a given object with default properties.
_.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- if (obj[prop] === void 0) obj[prop] = source[prop];
- }
+ if (!_.isObject(obj)) return obj;
+ for (var i = 1, length = arguments.length; i < length; i++) {
+ var source = arguments[i];
+ for (var prop in source) {
+ if (obj[prop] === void 0) obj[prop] = source[prop];
}
- });
+ }
return obj;
};
@@ -903,7 +974,7 @@
var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
- if (a === b) return a !== 0 || 1 / a == 1 / b;
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
@@ -911,29 +982,27 @@
if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names.
var className = toString.call(a);
- if (className != toString.call(b)) return false;
+ if (className !== toString.call(b)) return false;
switch (className) {
- // Strings, numbers, dates, and booleans are compared by value.
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
+ case '[object RegExp]':
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
- return a == String(b);
+ return '' + a === '' + b;
case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
- // other numeric values.
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ // `NaN`s are equivalent, but non-reflexive.
+ // Object(NaN) is equivalent to NaN
+ if (+a !== +a) return +b !== +b;
+ // An `egal` comparison is performed for other numeric values.
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
- return +a == +b;
- // RegExps are compared by their source patterns and flags.
- case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
+ return +a === +b;
}
if (typeof a != 'object' || typeof b != 'object') return false;
// Assume equality for cyclic structures. The algorithm for detecting cyclic
@@ -942,25 +1011,29 @@
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
- if (aStack[length] == a) return bStack[length] == b;
+ if (aStack[length] === a) return bStack[length] === b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))
- && ('constructor' in a && 'constructor' in b)) {
+ if (
+ aCtor !== bCtor &&
+ // Handle Object.create(x) cases
+ 'constructor' in a && 'constructor' in b &&
+ !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
+ _.isFunction(bCtor) && bCtor instanceof bCtor)
+ ) {
return false;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
- var size = 0, result = true;
+ var size, result;
// Recursively compare objects and arrays.
- if (className == '[object Array]') {
+ if (className === '[object Array]') {
// Compare array lengths to determine if a deep comparison is necessary.
size = a.length;
- result = size == b.length;
+ result = size === b.length;
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
@@ -969,21 +1042,17 @@
}
} else {
// Deep compare objects.
- for (var key in a) {
- if (_.has(a, key)) {
- // Count the expected number of properties.
- size++;
- // Deep compare each member.
+ var keys = _.keys(a), key;
+ size = keys.length;
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
+ result = _.keys(b).length === size;
+ if (result) {
+ while (size--) {
+ // Deep compare each member
+ key = keys[size];
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
}
}
- // Ensure that both objects contain the same number of properties.
- if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
@@ -1000,7 +1069,7 @@
// An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) {
if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false;
return true;
};
@@ -1013,18 +1082,19 @@
// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
+ return toString.call(obj) === '[object Array]';
};
// Is a given variable an object?
_.isObject = function(obj) {
- return obj === Object(obj);
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+ _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
_['is' + name] = function(obj) {
- return toString.call(obj) == '[object ' + name + ']';
+ return toString.call(obj) === '[object ' + name + ']';
};
});
@@ -1032,14 +1102,14 @@
// there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
+ return _.has(obj, 'callee');
};
}
- // Optimize `isFunction` if appropriate.
- if (typeof (/./) !== 'function') {
+ // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
+ if (typeof /./ !== 'function') {
_.isFunction = function(obj) {
- return typeof obj === 'function';
+ return typeof obj == 'function' || false;
};
}
@@ -1050,12 +1120,12 @@
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) {
- return _.isNumber(obj) && obj != +obj;
+ return _.isNumber(obj) && obj !== +obj;
};
// Is a given value a boolean?
_.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
};
// Is a given value equal to null?
@@ -1071,7 +1141,7 @@
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
+ return obj != null && hasOwnProperty.call(obj, key);
};
// Utility Functions
@@ -1084,17 +1154,19 @@
return this;
};
- // Keep the identity function around for default iterators.
+ // Keep the identity function around for default iteratees.
_.identity = function(value) {
return value;
};
_.constant = function(value) {
- return function () {
+ return function() {
return value;
};
};
+ _.noop = function(){};
+
_.property = function(key) {
return function(obj) {
return obj[key];
@@ -1103,20 +1175,23 @@
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_.matches = function(attrs) {
+ var pairs = _.pairs(attrs), length = pairs.length;
return function(obj) {
- if (obj === attrs) return true; //avoid comparing an object to itself.
- for (var key in attrs) {
- if (attrs[key] !== obj[key])
- return false;
+ if (obj == null) return !length;
+ obj = new Object(obj);
+ for (var i = 0; i < length; i++) {
+ var pair = pairs[i], key = pair[0];
+ if (pair[1] !== obj[key] || !(key in obj)) return false;
}
return true;
- }
+ };
};
// Run a function **n** times.
- _.times = function(n, iterator, context) {
+ _.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n));
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+ iteratee = createCallback(iteratee, context, 1);
+ for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum;
};
@@ -1130,54 +1205,44 @@
};
// A (possibly faster) way to get the current timestamp as an integer.
- _.now = Date.now || function() { return new Date().getTime(); };
-
- // List of HTML entities for escaping.
- var entityMap = {
- escape: {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- }
+ _.now = Date.now || function() {
+ return new Date().getTime();
};
- entityMap.unescape = _.invert(entityMap.escape);
- // Regexes containing the keys and values listed immediately above.
- var entityRegexes = {
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+ // List of HTML entities for escaping.
+ var escapeMap = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '`': '`'
};
+ var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation.
- _.each(['escape', 'unescape'], function(method) {
- _[method] = function(string) {
- if (string == null) return '';
- return ('' + string).replace(entityRegexes[method], function(match) {
- return entityMap[method][match];
- });
+ var createEscaper = function(map) {
+ var escaper = function(match) {
+ return map[match];
};
- });
+ // Regexes for identifying a key that needs to be escaped
+ var source = '(?:' + _.keys(map).join('|') + ')';
+ var testRegexp = RegExp(source);
+ var replaceRegexp = RegExp(source, 'g');
+ return function(string) {
+ string = string == null ? '' : '' + string;
+ return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+ };
+ };
+ _.escape = createEscaper(escapeMap);
+ _.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it.
_.result = function(object, property) {
if (object == null) return void 0;
var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
-
- // Add your own custom functions to the Underscore object.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name) {
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
- });
+ return _.isFunction(value) ? object[property]() : value;
};
// Generate a unique integer id (unique within the entire client session).
@@ -1208,22 +1273,26 @@
'\\': '\\',
'\r': 'r',
'\n': 'n',
- '\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+ var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
+
+ var escapeChar = function(match) {
+ return '\\' + escapes[match];
+ };
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- var render;
+ // NB: `oldSettings` only exists for backwards compatibility.
+ _.template = function(text, settings, oldSettings) {
+ if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
- var matcher = new RegExp([
+ var matcher = RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
@@ -1233,19 +1302,18 @@
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset)
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
+ source += text.slice(index, offset).replace(escaper, escapeChar);
+ index = offset + match.length;
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- }
- if (interpolate) {
+ } else if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- }
- if (evaluate) {
+ } else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
- index = offset + match.length;
+
+ // Adobe VMs need the match returned to produce the correct offest.
return match;
});
source += "';\n";
@@ -1255,29 +1323,31 @@
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
- source + "return __p;\n";
+ source + 'return __p;\n';
try {
- render = new Function(settings.variable || 'obj', '_', source);
+ var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
- if (data) return render(data, _);
var template = function(data) {
return render.call(this, data, _);
};
- // Provide the compiled function source as a convenience for precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+ // Provide the compiled source as a convenience for precompilation.
+ var argument = settings.variable || 'obj';
+ template.source = 'function(' + argument + '){\n' + source + '}';
return template;
};
- // Add a "chain" function, which will delegate to the wrapper.
+ // Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) {
- return _(obj).chain();
+ var instance = _(obj);
+ instance._chain = true;
+ return instance;
};
// OOP
@@ -1291,42 +1361,44 @@
return this._chain ? _(obj).chain() : obj;
};
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ _.each(_.functions(obj), function(name) {
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result.call(this, func.apply(_, args));
+ };
+ });
+ };
+
// Add all of the Underscore functions to the wrapper object.
_.mixin(_);
// Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
var obj = this._wrapped;
method.apply(obj, arguments);
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+ if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result.call(this, obj);
};
});
// Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
+ _.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
return result.call(this, method.apply(this._wrapped, arguments));
};
});
- _.extend(_.prototype, {
-
- // Start chaining a wrapped Underscore object.
- chain: function() {
- this._chain = true;
- return this;
- },
-
- // Extracts the result from a wrapped and chained object.
- value: function() {
- return this._wrapped;
- }
-
- });
+ // Extracts the result from a wrapped and chained object.
+ _.prototype.value = function() {
+ return this._wrapped;
+ };
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
@@ -1340,4 +1412,4 @@
return _;
});
}
-}).call(this);
+}.call(this));
diff --git a/node_modules/wrench/lib/wrench.js b/node_modules/wrench/lib/wrench.js
index 00f4166b..01f5e957 100644
--- a/node_modules/wrench/lib/wrench.js
+++ b/node_modules/wrench/lib/wrench.js
@@ -12,8 +12,8 @@
*/
var fs = require("fs"),
- _path = require("path");
-
+ _path = require("path"),
+ isWindows = !!process.platform.match(/^win/);
/* wrench.readdirSyncRecursive("directory_path");
*
@@ -28,7 +28,7 @@ exports.readdirSyncRecursive = function(baseDir) {
curFiles,
nextDirs,
isDir = function(fname){
- return fs.statSync( _path.join(baseDir, fname) ).isDirectory();
+ return fs.existsSync(_path.join(baseDir, fname)) ? fs.statSync( _path.join(baseDir, fname) ).isDirectory() : false;
},
prependBaseDir = function(fname){
return _path.join(baseDir, fname);
@@ -71,15 +71,16 @@ exports.readdirRecursive = function(baseDir, fn) {
var waitCount = 0;
function readdirRecursive(curDir) {
- var files = [],
- curFiles,
- nextDirs,
- prependcurDir = function(fname){
- return _path.join(curDir, fname);
- };
+ var prependcurDir = function(fname){
+ return _path.join(curDir, fname);
+ };
waitCount++;
fs.readdir(curDir, function(e, curFiles) {
+ if (e) {
+ fn(e);
+ return;
+ }
waitCount--;
curFiles = curFiles.map(prependcurDir);
@@ -120,7 +121,9 @@ exports.readdirRecursive = function(baseDir, fn) {
-/* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
+
+
+/* wrench.rmdirSyncRecursive("directory_path", failSilent);
*
* Recursively dives through directories and obliterates everything about it. This is a
* Sync-function, which blocks things until it's done. No idea why anybody would want an
@@ -132,44 +135,110 @@ exports.rmdirSyncRecursive = function(path, failSilent) {
try {
files = fs.readdirSync(path);
} catch (err) {
+
if(failSilent) return;
throw new Error(err.message);
}
/* Loop through and delete everything in the sub-tree after checking it */
for(var i = 0; i < files.length; i++) {
- var currFile = fs.lstatSync(path + "/" + files[i]);
+ var file = _path.join(path, files[i]);
+ var currFile = fs.lstatSync(file);
- if(currFile.isDirectory()) // Recursive function back to the beginning
- exports.rmdirSyncRecursive(path + "/" + files[i]);
+ if(currFile.isDirectory()) {
+ // Recursive function back to the beginning
+ exports.rmdirSyncRecursive(file);
+ } else if(currFile.isSymbolicLink()) {
+ // Unlink symlinks
+ if (isWindows) {
+ fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved..
+ }
- else if(currFile.isSymbolicLink()) // Unlink symlinks
- fs.unlinkSync(path + "/" + files[i]);
+ fs.unlinkSync(file);
+ } else {
+ // Assume it's a file - perhaps a try/catch belongs here?
+ if (isWindows) {
+ fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved..
+ }
- else // Assume it's a file - perhaps a try/catch belongs here?
- fs.unlinkSync(path + "/" + files[i]);
+ fs.unlinkSync(file);
+ }
}
/* Now that we know everything in the sub-tree has been deleted, we can delete the main
- directory. Huzzah for the shopkeep. */
+ directory. Huzzah for the shopkeep. */
return fs.rmdirSync(path);
};
+
+
+function isFileIncluded(opts, dir, filename) {
+
+ function isMatch(filter) {
+ if (typeof filter === 'function') {
+ return filter(filename, dir) === true;
+ }
+ else {
+ // Maintain backwards compatibility and use just the filename
+ return filename.match(filter);
+ }
+ }
+
+ if (opts.include || opts.exclude) {
+ if (opts.exclude) {
+ if (isMatch(opts.exclude)) {
+ return false;
+ }
+ }
+
+ if (opts.include) {
+ if (isMatch(opts.include)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ else if (opts.filter) {
+ var filter = opts.filter;
+
+ if (!opts.whitelist) {
+ // if !opts.whitelist is false every file or directory
+ // which does match opts.filter will be ignored
+ return isMatch(filter) ? false : true;
+ } else {
+ // if opts.whitelist is true every file or directory
+ // which doesn't match opts.filter will be ignored
+ return !isMatch(filter) ? false : true;
+ }
+ }
+
+ return true;
+}
+
/* wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts);
*
* Recursively dives through a directory and moves all its files to a new location. This is a
* Synchronous function, which blocks things until it's done. If you need/want to do this in
- * an Asynchronous manner, look at wrench.copyDirRecursively() below.
+ * an Asynchronous manner, look at wrench.copyDirRecursively() below. Specify forceDelete to force directory overwrite.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) {
+ opts = opts || {};
- if (!opts || !opts.preserve) {
- try {
- if(fs.statSync(newDirLocation).isDirectory()) exports.rmdirSyncRecursive(newDirLocation);
- } catch(e) { }
- }
+ try {
+ if(fs.statSync(newDirLocation).isDirectory()) {
+ if(opts.forceDelete) {
+ exports.rmdirSyncRecursive(newDirLocation);
+ } else {
+ return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~');
+ }
+ }
+ } catch(e) { }
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
var checkDir = fs.statSync(sourceDir);
@@ -181,20 +250,58 @@ exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) {
}
var files = fs.readdirSync(sourceDir);
+ var hasFilter = opts.filter || opts.include || opts.exclude;
+ var preserveFiles = opts.preserveFiles === true;
+ var preserveTimestamps = opts.preserveTimestamps === true;
for(var i = 0; i < files.length; i++) {
- var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
+ // ignores all files or directories which match the RegExp in opts.filter
+ if(typeof opts !== 'undefined') {
+ if (hasFilter) {
+ if (!isFileIncluded(opts, sourceDir, files[i])) {
+ continue;
+ }
+ }
+
+ if (opts.excludeHiddenUnix && /^\./.test(files[i])) continue;
+ }
+
+ var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));
+
+ var fCopyFile = function(srcFile, destFile) {
+ if(typeof opts !== 'undefined' && opts.preserveFiles && fs.existsSync(destFile)) return;
+
+ var contents = fs.readFileSync(srcFile);
+ fs.writeFileSync(destFile, contents);
+ var stat = fs.lstatSync(srcFile);
+ fs.chmodSync(destFile, stat.mode);
+ if (preserveTimestamps) {
+ fs.utimesSync(destFile, stat.atime, stat.mtime)
+ }
+ };
if(currFile.isDirectory()) {
/* recursion this thing right on back. */
- exports.copyDirSyncRecursive(sourceDir + "/" + files[i], newDirLocation + "/" + files[i], opts);
+ exports.copyDirSyncRecursive(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]), opts);
} else if(currFile.isSymbolicLink()) {
- var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]);
- fs.symlinkSync(symlinkFull, newDirLocation + "/" + files[i]);
+ var symlinkFull = fs.readlinkSync(_path.join(sourceDir, files[i]));
+ symlinkFull = _path.resolve(fs.realpathSync(sourceDir), symlinkFull);
+
+ if (typeof opts !== 'undefined' && !opts.inflateSymlinks) {
+ fs.symlinkSync(symlinkFull, _path.join(newDirLocation, files[i]));
+ continue;
+ }
+
+ var tmpCurrFile = fs.lstatSync(symlinkFull);
+ if (tmpCurrFile.isDirectory()) {
+ exports.copyDirSyncRecursive(symlinkFull, _path.join(newDirLocation, files[i]), opts);
+ } else {
+ /* At this point, we've hit a file actually worth copying... so copy it on over. */
+ fCopyFile(symlinkFull, _path.join(newDirLocation, files[i]));
+ }
} else {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
- var contents = fs.readFileSync(sourceDir + "/" + files[i]);
- fs.writeFileSync(newDirLocation + "/" + files[i], contents);
+ fCopyFile(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]));
}
}
};
@@ -210,14 +317,14 @@ exports.chmodSyncRecursive = function(sourceDir, filemode) {
var files = fs.readdirSync(sourceDir);
for(var i = 0; i < files.length; i++) {
- var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
+ var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));
if(currFile.isDirectory()) {
/* ...and recursion this thing right on back. */
- exports.chmodSyncRecursive(sourceDir + "/" + files[i], filemode);
+ exports.chmodSyncRecursive(_path.join(sourceDir, files[i]), filemode);
} else {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
- fs.chmod(sourceDir + "/" + files[i], filemode);
+ fs.chmod(_path.join(sourceDir, files[i]), filemode);
}
}
@@ -237,14 +344,14 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) {
var files = fs.readdirSync(sourceDir);
for(var i = 0; i < files.length; i++) {
- var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
+ var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));
if(currFile.isDirectory()) {
/* ...and recursion this thing right on back. */
- exports.chownSyncRecursive(sourceDir + "/" + files[i], uid, gid);
+ exports.chownSyncRecursive(_path.join(sourceDir, files[i]), uid, gid);
} else {
/* At this point, we've hit a file actually worth chowning... so own it. */
- fs.chownSync(sourceDir + "/" + files[i], uid, gid);
+ fs.chownSync(_path.join(sourceDir, files[i]), uid, gid);
}
}
@@ -258,9 +365,17 @@ exports.chownSyncRecursive = function(sourceDir, uid, gid) {
*
* Recursively dives through directories and obliterates everything about it.
*/
-exports.rmdirRecursive = function rmdirRecursive(dir, clbk){
- fs.readdir(dir, function(err, files){
- if (err) return clbk(err);
+exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){
+ if(clbk === null || typeof clbk == 'undefined')
+ clbk = function(err) {};
+
+ fs.readdir(dir, function(err, files) {
+ if(err && typeof failSilent === 'boolean' && !failSilent)
+ return clbk(err);
+
+ if(typeof failSilent === 'function')
+ clbk = failSilent;
+
(function rmFile(err){
if (err) return clbk(err);
@@ -269,7 +384,7 @@ exports.rmdirRecursive = function rmdirRecursive(dir, clbk){
return fs.rmdir(dir, clbk);
var file = dir+'/'+filename;
- fs.stat(file, function(err, stat){
+ fs.lstat(file, function(err, stat){
if (err) return clbk(err);
if (stat.isDirectory())
rmdirRecursive(file, rmFile);
@@ -280,18 +395,30 @@ exports.rmdirRecursive = function rmdirRecursive(dir, clbk){
});
};
-/* wrench.copyDirRecursive("directory_to_copy", "new_location", callback);
+/* wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback);
*
* Recursively dives through a directory and moves all its files to a new
- * location.
+ * location. Specify forceDelete to force directory overwrite.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
-exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, clbk) {
- fs.stat(newDir, function(err, newDirStat){
- if (!err) return exports.rmdirRecursive(newDir, function(err){
- copyDirRecursive(srcDir, newDir, clbk);
- });
+exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) {
+ var originalArguments = Array.prototype.slice.apply(arguments);
+ srcDir = _path.normalize(srcDir);
+ newDir = _path.normalize(newDir);
+
+ fs.stat(newDir, function(err, newDirStat) {
+ if(!err) {
+ if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete)
+ return exports.rmdirRecursive(newDir, function(err) {
+ copyDirRecursive.apply(this, originalArguments);
+ });
+ else
+ return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.'));
+ }
+
+ if(typeof opts === 'function')
+ clbk = opts;
fs.stat(srcDir, function(err, srcDirStat){
if (err) return clbk(err);
@@ -304,20 +431,23 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, clbk) {
var filename = files.shift();
if (filename === null || typeof filename == 'undefined')
- return clbk();
+ return clbk(null);
var file = srcDir+'/'+filename,
newFile = newDir+'/'+filename;
fs.stat(file, function(err, fileStat){
+ if (err) return clbk(err);
if (fileStat.isDirectory())
- copyDirRecursive(file, newFile, copyFiles);
+ copyDirRecursive(file, newFile, copyFiles, clbk);
else if (fileStat.isSymbolicLink())
fs.readlink(file, function(err, link){
+ if (err) return clbk(err);
fs.symlink(link, newFile, copyFiles);
});
else
fs.readFile(file, function(err, data){
+ if (err) return clbk(err);
fs.writeFile(newFile, data, copyFiles);
});
});
@@ -330,15 +460,13 @@ exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, clbk) {
var mkdirSyncRecursive = function(path, mode) {
var self = this;
+ path = _path.normalize(path)
try {
fs.mkdirSync(path, mode);
} catch(err) {
if(err.code == "ENOENT") {
- var slashIdx = path.lastIndexOf("/");
- if(slashIdx < 0) {
- slashIdx = path.lastIndexOf("\\");
- }
+ var slashIdx = path.lastIndexOf(_path.sep);
if(slashIdx > 0) {
var parentPath = path.substring(0, slashIdx);
@@ -364,6 +492,10 @@ exports.LineReader = function(filename, bufferSize) {
};
exports.LineReader.prototype = {
+ close: function() {
+ return fs.closeSync(this.fd);
+ },
+
getBufferAndSetCurrentPosition: function(position) {
var res = fs.readSync(this.fd, this.bufferSize, position, "ascii");
@@ -383,13 +515,13 @@ exports.LineReader.prototype = {
if(this.currentPosition === -1) return false;
}
- if(this.buffer.indexOf("\n") > -1) return true;
+ if(this.buffer.indexOf("\n") > -1 || this.buffer.length !== 0) return true;
return false;
},
getNextLine: function() {
var lineEnd = this.buffer.indexOf("\n"),
- result = this.buffer.substring(0, lineEnd);
+ result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length);
this.buffer = this.buffer.substring(result.length + 1, this.buffer.length);
return result;
diff --git a/node_modules/wrench/package.json b/node_modules/wrench/package.json
index 80124ffe..7cd149cd 100644
--- a/node_modules/wrench/package.json
+++ b/node_modules/wrench/package.json
@@ -1,7 +1,7 @@
{
"name": "wrench",
"description": "Recursive filesystem (and other) operations that Node *should* have.",
- "version": "1.3.9",
+ "version": "1.5.8",
"author": {
"name": "Ryan McGrath",
"email": "ryan@venodesigns.net"
@@ -33,11 +33,11 @@
"url": "http://github.com/ryanmcgrath/wrench-js/raw/master/LICENSE"
}
],
- "readme": "wrench.js - Recursive file operations in Node.js\n----------------------------------------------------------------------------\nWhile I love Node.js, I've found myself missing some functions. Things like\nrecursively deleting/chmodding a directory (or even deep copying a directory),\nor even a basic line reader, shouldn't need to be re-invented time and time again.\n\nThat said, here's my attempt at a re-usable solution, at least until something\nmore formalized gets integrated into Node.js (*hint hint*). wrench.js is fairly simple\nto use - check out the documentation/examples below:\n\nInstallation\n-----------------------------------------------------------------------------\n\n npm install wrench\n\nUsage\n-----------------------------------------------------------------------------\n``` javascript\nvar wrench = require('wrench'),\n\tutil = require('util');\n```\n\n### Synchronous operations\n``` javascript\n// Recursively create directories, sub-trees and all.\nwrench.mkdirSyncRecursive(dir, 0777);\n\n// Recursively delete the entire sub-tree of a directory, then kill the directory\nwrench.rmdirSyncRecursive('my_directory_name', failSilently);\n\n// Recursively read directories contents.\nwrench.readdirSyncRecursive('my_directory_name');\n\n// Recursively chmod the entire sub-tree of a directory\nwrench.chmodSyncRecursive('my_directory_name', 0755);\n\n// Recursively chown the entire sub-tree of a directory\nwrench.chownSyncRecursive(\"directory\", uid, gid);\n\n// Deep-copy an existing directory\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up');\n\n// Read lines in from a file until you hit the end\nvar f = new wrench.LineReader('x.txt');\nwhile(f.hasNextLine()) {\n\tutil.puts(x.getNextLine());\n}\n```\n\n### Asynchronous operations\n``` javascript\n// Recursively read directories contents\nvar files = [];\nwrench.readdirRecursive('my_directory_name', function(error, curFiles) {\n // curFiles is what you want\n});\n\n```\n\nQuestions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)\n",
+ "readme": "wrench.js - Recursive file operations in Node.js\n----------------------------------------------------------------------------\nWhile I love Node.js, I've found myself missing some functions. Things like\nrecursively deleting/chmodding a directory (or even deep copying a directory),\nor even a basic line reader, shouldn't need to be re-invented time and time again.\n\nThat said, here's my attempt at a re-usable solution, at least until something\nmore formalized gets integrated into Node.js (*hint hint*). wrench.js is fairly simple\nto use - check out the documentation/examples below:\n\nPossibly Breaking Change in v1.5.0\n-----------------------------------------------------------------------------\nIn previous versions of Wrench, we went against the OS-default behavior of not\ndeleting a directory unless the operation is forced. In 1.5.0, this has been\nchanged to be the behavior people expect there to be - if you try to copy over\na directory that already exists, you'll get an Error returned or thrown stating\nthat you need to force it.\n\nSomething like this will do the trick:\n\n``` javascript\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {\n forceDelete: true\n});\n```\n\nIf you desire the older behavior of Wrench... hit up your package.json. If you\nhappen to find bugs in the 1.5.0 release please feel free to file them on the \nGitHub issues tracker for this project, or send me a pull request and I'll get to\nit as fast as I can. Thanks!\n\n**If this breaks enough projects I will consider rolling it back. Please hit me up if this seems to be the case.**\n\nInstallation\n-----------------------------------------------------------------------------\n\n npm install wrench\n\nUsage\n-----------------------------------------------------------------------------\n``` javascript\nvar wrench = require('wrench'),\n\tutil = require('util');\n```\n\n### Synchronous operations\n``` javascript\n// Recursively create directories, sub-trees and all.\nwrench.mkdirSyncRecursive(dir, 0777);\n\n// Recursively delete the entire sub-tree of a directory, then kill the directory\nwrench.rmdirSyncRecursive('my_directory_name', failSilently);\n\n// Recursively read directories contents.\nwrench.readdirSyncRecursive('my_directory_name');\n\n// Recursively chmod the entire sub-tree of a directory\nwrench.chmodSyncRecursive('my_directory_name', 0755);\n\n// Recursively chown the entire sub-tree of a directory\nwrench.chownSyncRecursive(\"directory\", uid, gid);\n\n// Deep-copy an existing directory\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {\n forceDelete: bool, // Whether to overwrite existing directory or not\n excludeHiddenUnix: bool, // Whether to copy hidden Unix files or not (preceding .)\n preserveFiles: bool, // If we're overwriting something and the file already exists, keep the existing\n preserveTimestamps: bool, // Preserve the mtime and atime when copying files\n inflateSymlinks: bool, // Whether to follow symlinks or not when copying files\n filter: regexpOrFunction, // A filter to match files against; if matches, do nothing (exclude).\n whitelist: bool, // if true every file or directory which doesn't match filter will be ignored\n include: regexpOrFunction, // An include filter (either a regexp or a function)\n exclude: regexpOrFunction // An exclude filter (either a regexp or a function)\n});\n\n// Note: If a RegExp is provided then then it will be matched against the filename. If a function is\n// provided then the signature should be the following:\n// function(filename, dir) { return result; }\n\n// Read lines in from a file until you hit the end\nvar f = new wrench.LineReader('x.txt');\nwhile(f.hasNextLine()) {\n\tutil.puts(f.getNextLine());\n}\n\n// Note: You will need to close that above line reader at some point, otherwise\n// you will run into a \"too many open files\" error. f.close() or fs.closeSync(f.fd) are\n// your friends, as only you know when it is safe to close.\n```\n\n### Asynchronous operations\n``` javascript\n// Recursively read directories contents\nvar files = [];\nwrench.readdirRecursive('my_directory_name', function(error, curFiles) {\n // curFiles is what you want\n});\n\n// If you're feeling somewhat masochistic\nwrench.copyDirRecursive(srcDir, newDir, {forceDelete: bool /* See sync version */}, callbackfn);\n```\n\nQuestions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)\n",
"readmeFilename": "readme.md",
"homepage": "https://github.com/ryanmcgrath/wrench-js",
- "_id": "wrench@1.3.9",
- "_shasum": "6f13ec35145317eb292ca5f6531391b244111411",
- "_from": "wrench@1.3.9",
- "_resolved": "https://registry.npmjs.org/wrench/-/wrench-1.3.9.tgz"
+ "_id": "wrench@1.5.8",
+ "_shasum": "7a31c97f7869246d76c5cf2f5c977a1c4c8e5ab5",
+ "_from": "wrench@~1.5.8",
+ "_resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz"
}
diff --git a/package.json b/package.json
index 5a9efffa..d3829fbf 100644
--- a/package.json
+++ b/package.json
@@ -13,17 +13,17 @@
"url": "https://github.com/jsdoc3/jsdoc"
},
"dependencies": {
- "async": "~0.1.22",
+ "async": "~0.9.0",
"catharsis": "~0.8.6",
- "escape-string-regexp": "~1.0.0",
+ "escape-string-regexp": "~1.0.2",
"esprima": "https://github.com/ariya/esprima/tarball/49a2eccb243f29bd653b11e9419241a9d726af7c",
- "js2xmlparser": "~0.1.0",
- "marked": "~0.3.1",
+ "js2xmlparser": "~0.1.7",
+ "marked": "~0.3.2",
"requizzle": "~0.2.0",
- "strip-json-comments": "~0.1.3",
- "taffydb": "https://github.com/hegemonic/taffydb/tarball/master",
- "underscore": "~1.6.0",
- "wrench": "~1.3.9"
+ "strip-json-comments": "~1.0.2",
+ "taffydb": "https://github.com/hegemonic/taffydb/tarball/7d100bcee0e997ee4977e273cdce60bd8933050e",
+ "underscore": "~1.7.0",
+ "wrench": "~1.5.8"
},
"devDependencies": {
"eslint": "~0.11.0",
diff --git a/rhino/os.js b/rhino/os.js
index e3d2b787..80473b62 100644
--- a/rhino/os.js
+++ b/rhino/os.js
@@ -1,3 +1,4 @@
+/*global java */
/**
* Partial Rhino implementation of Node.js' `os` module.
* @module os
@@ -8,12 +9,6 @@
exports.EOL = String( java.lang.System.getProperty('line.separator') );
-// clearly not accurate, but probably good enough
exports.platform = function() {
- if ( String(java.lang.System.getProperty('os.name')).match(/^[Ww]in/) ) {
- return 'win32';
- }
- else {
- return 'linux';
- }
-};
\ No newline at end of file
+ return process.platform;
+};
diff --git a/rhino/rhino-shim.js b/rhino/rhino-shim.js
index 720202f9..297a5797 100644
--- a/rhino/rhino-shim.js
+++ b/rhino/rhino-shim.js
@@ -1,4 +1,5 @@
-/*global env: true, Packages: true */
+/*global env, java, Packages, version */
+/*eslint-disable strict */
/**
* @overview A minimal emulation of the standard features of Node.js necessary
* to get JSDoc to run.
@@ -149,6 +150,15 @@ global.process = {
nextTick: function nextTick(callback) {
setTimeout(callback, 0);
},
+ platform: (function() {
+ if ( String(java.lang.System.getProperty('os.name')).match(/^[Ww]in/) ) {
+ return 'win32';
+ }
+ else {
+ // not necessarily accurate, but good enough
+ return 'linux';
+ }
+ })(),
stderr: {
// Java can't reliably find the terminal width across platforms, so we hard-code a
// reasonable value