update Underscore.js dependency

This commit is contained in:
Jeff Williams 2014-05-29 22:54:54 -04:00
parent 57b562f1b4
commit 9555f6c43f
5 changed files with 371 additions and 201 deletions

View File

@ -365,10 +365,11 @@ https://github.com/geraintluff/tv4
Underscore.js is distributed under the MIT license, which is reproduced above. Underscore.js is distributed under the MIT license, which is reproduced above.
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud. Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors.
The source code for Underscore.js is available at: The source code for Underscore.js is available at:
https://github.com/documentcloud/underscore https://github.com/jashkenas/underscore
## wrench-js ## ## wrench-js ##

5
node_modules/underscore/LICENSE generated vendored
View File

@ -1,4 +1,5 @@
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation
@ -19,4 +20,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.

35
node_modules/underscore/package.json generated vendored
View File

@ -15,11 +15,36 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/documentcloud/underscore.git" "url": "git://github.com/jashkenas/underscore.git"
}, },
"main": "underscore.js", "main": "underscore.js",
"version": "1.4.2", "version": "1.6.0",
"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\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n", "devDependencies": {
"_id": "underscore@1.4.2", "docco": "0.6.x",
"_from": "underscore" "phantomjs": "1.9.0-1",
"uglify-js": "2.4.x"
},
"scripts": {
"test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true",
"build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js",
"doc": "docco underscore.js"
},
"licenses": [
{
"type": "MIT",
"url": "https://raw.github.com/jashkenas/underscore/master/LICENSE"
}
],
"files": [
"underscore.js",
"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",
"bugs": {
"url": "https://github.com/jashkenas/underscore/issues"
},
"_id": "underscore@1.6.0",
"_from": "underscore@~1.6.0"
} }

525
node_modules/underscore/underscore.js generated vendored
View File

@ -1,6 +1,6 @@
// Underscore.js 1.4.2 // Underscore.js 1.6.0
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
@ -8,7 +8,7 @@
// Baseline setup // Baseline setup
// -------------- // --------------
// Establish the root object, `window` in the browser, or `global` on the server. // Establish the root object, `window` in the browser, or `exports` on the server.
var root = this; var root = this;
// Save the previous value of the `_` variable. // Save the previous value of the `_` variable.
@ -21,12 +21,12 @@
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
// Create quick reference variables for speed access to core prototypes. // Create quick reference variables for speed access to core prototypes.
var push = ArrayProto.push, var
slice = ArrayProto.slice, push = ArrayProto.push,
concat = ArrayProto.concat, slice = ArrayProto.slice,
unshift = ArrayProto.unshift, concat = ArrayProto.concat,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use // All **ECMAScript 5** native function implementations that we hope to use
// are declared here. // are declared here.
@ -61,11 +61,11 @@
} }
exports._ = _; exports._ = _;
} else { } else {
root['_'] = _; root._ = _;
} }
// Current version. // Current version.
_.VERSION = '1.4.2'; _.VERSION = '1.6.0';
// Collection Functions // Collection Functions
// -------------------- // --------------------
@ -74,20 +74,20 @@
// Handles objects with the built-in `forEach`, arrays, and raw objects. // Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available. // Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _.each = _.forEach = function(obj, iterator, context) { var each = _.each = _.forEach = function(obj, iterator, context) {
if (obj == null) return; if (obj == null) return obj;
if (nativeForEach && obj.forEach === nativeForEach) { if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context); obj.forEach(iterator, context);
} else if (obj.length === +obj.length) { } else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) { for (var i = 0, length = obj.length; i < length; i++) {
if (iterator.call(context, obj[i], i, obj) === breaker) return; if (iterator.call(context, obj[i], i, obj) === breaker) return;
} }
} else { } else {
for (var key in obj) { var keys = _.keys(obj);
if (_.has(obj, key)) { for (var i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[key], key, obj) === breaker) return; if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
}
} }
} }
return obj;
}; };
// Return the results of applying the iterator to each element. // Return the results of applying the iterator to each element.
@ -97,11 +97,13 @@
if (obj == null) return results; if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list); results.push(iterator.call(context, value, index, list));
}); });
return results; 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`, // **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
@ -119,7 +121,7 @@
memo = iterator.call(context, memo, value, index, list); memo = iterator.call(context, memo, value, index, list);
} }
}); });
if (!initial) throw new TypeError('Reduce of empty array with no initial value'); if (!initial) throw new TypeError(reduceError);
return memo; return memo;
}; };
@ -130,7 +132,7 @@
if (obj == null) obj = []; if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context); if (context) iterator = _.bind(iterator, context);
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
} }
var length = obj.length; var length = obj.length;
if (length !== +length) { if (length !== +length) {
@ -146,15 +148,15 @@
memo = iterator.call(context, memo, obj[index], index, list); memo = iterator.call(context, memo, obj[index], index, list);
} }
}); });
if (!initial) throw new TypeError('Reduce of empty array with no initial value'); if (!initial) throw new TypeError(reduceError);
return memo; return memo;
}; };
// Return the first value which passes a truth test. Aliased as `detect`. // Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, iterator, context) { _.find = _.detect = function(obj, predicate, context) {
var result; var result;
any(obj, function(value, index, list) { any(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) { if (predicate.call(context, value, index, list)) {
result = value; result = value;
return true; return true;
} }
@ -165,36 +167,33 @@
// Return all the elements that pass a truth test. // Return all the elements that pass a truth test.
// Delegates to **ECMAScript 5**'s native `filter` if available. // Delegates to **ECMAScript 5**'s native `filter` if available.
// Aliased as `select`. // Aliased as `select`.
_.filter = _.select = function(obj, iterator, context) { _.filter = _.select = function(obj, predicate, context) {
var results = []; var results = [];
if (obj == null) return results; if (obj == null) return results;
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) results[results.length] = value; if (predicate.call(context, value, index, list)) results.push(value);
}); });
return results; return results;
}; };
// Return all the elements for which a truth test fails. // Return all the elements for which a truth test fails.
_.reject = function(obj, iterator, context) { _.reject = function(obj, predicate, context) {
var results = []; return _.filter(obj, function(value, index, list) {
if (obj == null) return results; return !predicate.call(context, value, index, list);
each(obj, function(value, index, list) { }, context);
if (!iterator.call(context, value, index, list)) results[results.length] = value;
});
return results;
}; };
// Determine whether all of the elements match a truth test. // Determine whether all of the elements match a truth test.
// Delegates to **ECMAScript 5**'s native `every` if available. // Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`. // Aliased as `all`.
_.every = _.all = function(obj, iterator, context) { _.every = _.all = function(obj, predicate, context) {
iterator || (iterator = _.identity); predicate || (predicate = _.identity);
var result = true; var result = true;
if (obj == null) return result; if (obj == null) return result;
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (!(result = result && iterator.call(context, value, index, list))) return breaker; if (!(result = result && predicate.call(context, value, index, list))) return breaker;
}); });
return !!result; return !!result;
}; };
@ -202,13 +201,13 @@
// Determine if at least one element in the object matches a truth test. // Determine if at least one element in the object matches a truth test.
// Delegates to **ECMAScript 5**'s native `some` if available. // Delegates to **ECMAScript 5**'s native `some` if available.
// Aliased as `any`. // Aliased as `any`.
var any = _.some = _.any = function(obj, iterator, context) { var any = _.some = _.any = function(obj, predicate, context) {
iterator || (iterator = _.identity); predicate || (predicate = _.identity);
var result = false; var result = false;
if (obj == null) return result; if (obj == null) return result;
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker; if (result || (result = predicate.call(context, value, index, list))) return breaker;
}); });
return !!result; return !!result;
}; };
@ -216,54 +215,55 @@
// Determine if the array or object contains a given value (using `===`). // Determine if the array or object contains a given value (using `===`).
// Aliased as `include`. // Aliased as `include`.
_.contains = _.include = function(obj, target) { _.contains = _.include = function(obj, target) {
var found = false; if (obj == null) return false;
if (obj == null) return found;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
found = any(obj, function(value) { return any(obj, function(value) {
return value === target; return value === target;
}); });
return found;
}; };
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
_.invoke = function(obj, method) { _.invoke = function(obj, method) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (_.isFunction(method) ? method : value[method]).apply(value, args); return (isFunc ? method : value[method]).apply(value, args);
}); });
}; };
// Convenience version of a common use case of `map`: fetching a property. // Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) { _.pluck = function(obj, key) {
return _.map(obj, function(value){ return value[key]; }); return _.map(obj, _.property(key));
}; };
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// with specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs) {
if (_.isEmpty(attrs)) return []; return _.filter(obj, _.matches(attrs));
return _.filter(obj, function(value) { };
for (var key in attrs) {
if (attrs[key] !== value[key]) return false; // Convenience version of a common use case of `find`: getting the first object
} // containing specific `key:value` pairs.
return true; _.findWhere = function(obj, attrs) {
}); return _.find(obj, _.matches(attrs));
}; };
// Return the maximum element or (element-based computation). // Return the maximum element or (element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. // Can't optimize arrays of integers longer than 65,535 elements.
// See: https://bugs.webkit.org/show_bug.cgi?id=80797 // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
_.max = function(obj, iterator, context) { _.max = function(obj, iterator, context) {
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.max.apply(Math, obj); return Math.max.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return -Infinity; var result = -Infinity, lastComputed = -Infinity;
var result = {computed : -Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed >= result.computed && (result = {value : value, computed : computed}); if (computed > lastComputed) {
result = value;
lastComputed = computed;
}
}); });
return result.value; return result;
}; };
// Return the minimum element (or element-based computation). // Return the minimum element (or element-based computation).
@ -271,16 +271,19 @@
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
return Math.min.apply(Math, obj); return Math.min.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return Infinity; var result = Infinity, lastComputed = Infinity;
var result = {computed : Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed < result.computed && (result = {value : value, computed : computed}); if (computed < lastComputed) {
result = value;
lastComputed = computed;
}
}); });
return result.value; return result;
}; };
// Shuffle an array. // Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/FisherYates_shuffle).
_.shuffle = function(obj) { _.shuffle = function(obj) {
var rand; var rand;
var index = 0; var index = 0;
@ -293,19 +296,32 @@
return shuffled; return shuffled;
}; };
// Sample **n** random values from a collection.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (n == null || guard) {
if (obj.length !== +obj.length) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
};
// An internal function to generate lookup iterators. // An internal function to generate lookup iterators.
var lookupIterator = function(value) { var lookupIterator = function(value) {
return _.isFunction(value) ? value : function(obj){ return obj[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. // Sort the object's values by a criterion produced by an iterator.
_.sortBy = function(obj, value, context) { _.sortBy = function(obj, iterator, context) {
var iterator = lookupIterator(value); iterator = lookupIterator(iterator);
return _.pluck(_.map(obj, function(value, index, list) { return _.pluck(_.map(obj, function(value, index, list) {
return { return {
value : value, value: value,
index : index, index: index,
criteria : iterator.call(context, value, index, list) criteria: iterator.call(context, value, index, list)
}; };
}).sort(function(left, right) { }).sort(function(left, right) {
var a = left.criteria; var a = left.criteria;
@ -314,43 +330,46 @@
if (a > b || a === void 0) return 1; if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1; if (a < b || b === void 0) return -1;
} }
return left.index < right.index ? -1 : 1; return left.index - right.index;
}), 'value'); }), 'value');
}; };
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(obj, value, context, behavior) { var group = function(behavior) {
var result = {}; return function(obj, iterator, context) {
var iterator = lookupIterator(value); var result = {};
each(obj, function(value, index) { iterator = lookupIterator(iterator);
var key = iterator.call(context, value, index, obj); each(obj, function(value, index) {
behavior(result, key, value); var key = iterator.call(context, value, index, obj);
}); behavior(result, key, value);
return result; });
return result;
};
}; };
// Groups the object's values by a criterion. Pass either a string attribute // Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion. // to group by, or a function that returns the criterion.
_.groupBy = function(obj, value, context) { _.groupBy = group(function(result, key, value) {
return group(obj, value, context, function(result, key, value) { _.has(result, key) ? result[key].push(value) : result[key] = [value];
(_.has(result, key) ? result[key] : (result[key] = [])).push(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) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass // 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 // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = function(obj, value, context) { _.countBy = group(function(result, key) {
return group(obj, value, context, function(result, key, value) { _.has(result, key) ? result[key]++ : result[key] = 1;
if (!_.has(result, key)) result[key] = 0; });
result[key]++;
});
};
// Use a comparator function to figure out the smallest index at which // 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. // an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iterator, context) { _.sortedIndex = function(array, obj, iterator, context) {
iterator = iterator == null ? _.identity : lookupIterator(iterator); iterator = lookupIterator(iterator);
var value = iterator.call(context, obj); var value = iterator.call(context, obj);
var low = 0, high = array.length; var low = 0, high = array.length;
while (low < high) { while (low < high) {
@ -360,15 +379,17 @@
return low; return low;
}; };
// Safely convert anything iterable into a real, live array. // Safely create a real, live array from anything iterable.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (obj.length === +obj.length) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
// Return the number of elements in an object. // Return the number of elements in an object.
_.size = function(obj) { _.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;
}; };
@ -379,7 +400,10 @@
// values in the array. Aliased as `head` and `take`. The **guard** check // values in the array. Aliased as `head` and `take`. The **guard** check
// allows it to work with `_.map`. // allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) { _.first = _.head = _.take = function(array, n, guard) {
return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; if (array == null) return void 0;
if ((n == null) || guard) return array[0];
if (n < 0) return [];
return slice.call(array, 0, n);
}; };
// Returns everything but the last entry of the array. Especially useful on // Returns everything but the last entry of the array. Especially useful on
@ -393,11 +417,9 @@
// Get the last element of an array. Passing **n** will return the last 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`. // values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) { _.last = function(array, n, guard) {
if ((n != null) && !guard) { if (array == null) return void 0;
return slice.call(array, Math.max(array.length - n, 0)); if ((n == null) || guard) return array[array.length - 1];
} else { return slice.call(array, Math.max(array.length - n, 0));
return array[array.length - 1];
}
}; };
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
@ -410,13 +432,16 @@
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
_.compact = function(array) { _.compact = function(array) {
return _.filter(array, function(value){ return !!value; }); return _.filter(array, _.identity);
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) { var flatten = function(input, shallow, output) {
if (shallow && _.every(input, _.isArray)) {
return concat.apply(output, input);
}
each(input, function(value) { each(input, function(value) {
if (_.isArray(value)) { if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output); shallow ? push.apply(output, value) : flatten(value, shallow, output);
} else { } else {
output.push(value); output.push(value);
@ -425,7 +450,7 @@
return output; return output;
}; };
// Return a completely flattened version of an array. // Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) { _.flatten = function(array, shallow) {
return flatten(array, shallow, []); return flatten(array, shallow, []);
}; };
@ -435,10 +460,25 @@
return _.difference(array, slice.call(arguments, 1)); 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 // Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm. // been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`. // Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iterator, context) { _.uniq = _.unique = function(array, isSorted, iterator, context) {
if (_.isFunction(isSorted)) {
context = iterator;
iterator = isSorted;
isSorted = false;
}
var initial = iterator ? _.map(array, iterator, context) : array; var initial = iterator ? _.map(array, iterator, context) : array;
var results = []; var results = [];
var seen = []; var seen = [];
@ -454,7 +494,7 @@
// Produce an array that contains the union: each distinct element from all of // Produce an array that contains the union: each distinct element from all of
// the passed-in arrays. // the passed-in arrays.
_.union = function() { _.union = function() {
return _.uniq(concat.apply(ArrayProto, arguments)); return _.uniq(_.flatten(arguments, true));
}; };
// Produce an array that contains every item shared between all the // Produce an array that contains every item shared between all the
@ -463,7 +503,7 @@
var rest = slice.call(arguments, 1); var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) { return _.filter(_.uniq(array), function(item) {
return _.every(rest, function(other) { return _.every(rest, function(other) {
return _.indexOf(other, item) >= 0; return _.contains(other, item);
}); });
}); });
}; };
@ -478,11 +518,10 @@
// Zip together multiple lists into a single array -- elements that share // Zip together multiple lists into a single array -- elements that share
// an index go together. // an index go together.
_.zip = function() { _.zip = function() {
var args = slice.call(arguments); var length = _.max(_.pluck(arguments, 'length').concat(0));
var length = _.max(_.pluck(args, 'length'));
var results = new Array(length); var results = new Array(length);
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
results[i] = _.pluck(args, "" + i); results[i] = _.pluck(arguments, '' + i);
} }
return results; return results;
}; };
@ -491,8 +530,9 @@
// pairs, or two parallel arrays of the same length -- one of keys, and one of // pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. // the corresponding values.
_.object = function(list, values) { _.object = function(list, values) {
if (list == null) return {};
var result = {}; var result = {};
for (var i = 0, l = list.length; i < l; i++) { for (var i = 0, length = list.length; i < length; i++) {
if (values) { if (values) {
result[list[i]] = values[i]; result[list[i]] = values[i];
} else { } else {
@ -510,17 +550,17 @@
// for **isSorted** to use binary search. // for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) { _.indexOf = function(array, item, isSorted) {
if (array == null) return -1; if (array == null) return -1;
var i = 0, l = array.length; var i = 0, length = array.length;
if (isSorted) { if (isSorted) {
if (typeof isSorted == 'number') { if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
} else { } else {
i = _.sortedIndex(array, item); i = _.sortedIndex(array, item);
return array[i] === item ? i : -1; return array[i] === item ? i : -1;
} }
} }
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < l; i++) if (array[i] === item) return i; for (; i < length; i++) if (array[i] === item) return i;
return -1; return -1;
}; };
@ -546,11 +586,11 @@
} }
step = arguments[2] || 1; step = arguments[2] || 1;
var len = Math.max(Math.ceil((stop - start) / step), 0); var length = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0; var idx = 0;
var range = new Array(len); var range = new Array(length);
while(idx < len) { while(idx < length) {
range[idx++] = start; range[idx++] = start;
start += step; start += step;
} }
@ -565,29 +605,46 @@
var ctor = function(){}; var ctor = function(){};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Binding with arguments is also known as `curry`. // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// Delegates to **ECMAScript 5**'s native `Function.bind` if available. // available.
// We check for `func.bind` first, to fail fast when `func` is undefined. _.bind = function(func, context) {
_.bind = function bind(func, context) { var args, bound;
var bound, args; if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; if (!_.isFunction(func)) throw new TypeError;
args = slice.call(arguments, 2); args = slice.call(arguments, 2);
return bound = function() { return bound = function() {
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
ctor.prototype = func.prototype; ctor.prototype = func.prototype;
var self = new ctor; var self = new ctor;
ctor.prototype = null;
var result = func.apply(self, args.concat(slice.call(arguments))); var result = func.apply(self, args.concat(slice.call(arguments)));
if (Object(result) === result) return result; if (Object(result) === result) return result;
return self; return self;
}; };
}; };
// Bind all of an object's methods to that object. Useful for ensuring that // Partially apply a function by creating a version that has had some of its
// all callbacks defined on an object belong to it. // arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) {
var boundArgs = slice.call(arguments, 1);
return function() {
var position = 0;
var args = boundArgs.slice();
for (var i = 0, length = args.length; i < length; i++) {
if (args[i] === _) args[i] = arguments[position++];
}
while (position < arguments.length) args.push(arguments[position++]);
return func.apply(this, args);
};
};
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var funcs = slice.call(arguments, 1);
if (funcs.length == 0) funcs = _.functions(obj); if (funcs.length === 0) throw new Error('bindAll must be passed function names');
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
return obj; return obj;
}; };
@ -616,27 +673,36 @@
}; };
// Returns a function, that, when invoked, will only be triggered at most once // Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. // during a given window of time. Normally, the throttled function will run
_.throttle = function(func, wait) { // as much as it can, without ever going more than once per `wait` duration;
var context, args, timeout, throttling, more, result; // but if you'd like to disable the execution on the leading edge, pass
var whenDone = _.debounce(function(){ more = throttling = false; }, wait); // `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
options || (options = {});
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
context = args = null;
};
return function() { return function() {
context = this; args = arguments; var now = _.now();
var later = function() { if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null; timeout = null;
if (more) { previous = now;
result = func.apply(context, args);
}
whenDone();
};
if (!timeout) timeout = setTimeout(later, wait);
if (throttling) {
more = true;
} else {
throttling = true;
result = func.apply(context, args); result = func.apply(context, args);
context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
} }
whenDone();
return result; return result;
}; };
}; };
@ -646,17 +712,34 @@
// N milliseconds. If `immediate` is passed, trigger the function on the // N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing. // leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) { _.debounce = function(func, wait, immediate) {
var timeout, result; var timeout, args, context, timestamp, result;
return function() {
var context = this, args = arguments; var later = function() {
var later = function() { var last = _.now() - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null; timeout = null;
if (!immediate) result = func.apply(context, args); if (!immediate) {
}; result = func.apply(context, args);
context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout; var callNow = immediate && !timeout;
clearTimeout(timeout); if (!timeout) {
timeout = setTimeout(later, wait); timeout = setTimeout(later, wait);
if (callNow) result = func.apply(context, args); }
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result; return result;
}; };
}; };
@ -678,11 +761,7 @@
// allowing you to adjust arguments, run code before and after, and // allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function. // conditionally execute the original function.
_.wrap = function(func, wrapper) { _.wrap = function(func, wrapper) {
return function() { return _.partial(wrapper, func);
var args = [func];
push.apply(args, arguments);
return wrapper.apply(this, args);
};
}; };
// Returns a function that is the composition of a list of functions, each // Returns a function that is the composition of a list of functions, each
@ -700,7 +779,6 @@
// Returns a function that will only be executed after being called N times. // Returns a function that will only be executed after being called N times.
_.after = function(times, func) { _.after = function(times, func) {
if (times <= 0) return func();
return function() { return function() {
if (--times < 1) { if (--times < 1) {
return func.apply(this, arguments); return func.apply(this, arguments);
@ -713,31 +791,43 @@
// Retrieve the names of an object's properties. // Retrieve the names of an object's properties.
// Delegates to **ECMAScript 5**'s native `Object.keys` // Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = nativeKeys || function(obj) { _.keys = function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object'); if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj);
var keys = []; var keys = [];
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys; return keys;
}; };
// Retrieve the values of an object's properties. // Retrieve the values of an object's properties.
_.values = function(obj) { _.values = function(obj) {
var values = []; var keys = _.keys(obj);
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); var length = keys.length;
var values = new Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values; return values;
}; };
// Convert an object into a list of `[key, value]` pairs. // Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) { _.pairs = function(obj) {
var pairs = []; var keys = _.keys(obj);
for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); var length = keys.length;
var pairs = new Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs; return pairs;
}; };
// Invert the keys and values of an object. The values must be serializable. // Invert the keys and values of an object. The values must be serializable.
_.invert = function(obj) { _.invert = function(obj) {
var result = {}; var result = {};
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result; return result;
}; };
@ -754,8 +844,10 @@
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = function(obj) {
each(slice.call(arguments, 1), function(source) { each(slice.call(arguments, 1), function(source) {
for (var prop in source) { if (source) {
obj[prop] = source[prop]; for (var prop in source) {
obj[prop] = source[prop];
}
} }
}); });
return obj; return obj;
@ -784,8 +876,10 @@
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = function(obj) {
each(slice.call(arguments, 1), function(source) { each(slice.call(arguments, 1), function(source) {
for (var prop in source) { if (source) {
if (obj[prop] == null) obj[prop] = source[prop]; for (var prop in source) {
if (obj[prop] === void 0) obj[prop] = source[prop];
}
} }
}); });
return obj; return obj;
@ -808,7 +902,7 @@
// Internal recursive comparison function for `isEqual`. // Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) { var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical. // 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. // 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`. // A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b; if (a == null || b == null) return a === b;
@ -850,6 +944,14 @@
// unique nested structures. // 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)) {
return false;
}
// Add the first object to the stack of traversed objects. // Add the first object to the stack of traversed objects.
aStack.push(a); aStack.push(a);
bStack.push(b); bStack.push(b);
@ -866,13 +968,6 @@
} }
} }
} else { } else {
// 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))) {
return false;
}
// Deep compare objects. // Deep compare objects.
for (var key in a) { for (var key in a) {
if (_.has(a, key)) { if (_.has(a, key)) {
@ -950,7 +1045,7 @@
// Is a given object a finite number? // Is a given object a finite number?
_.isFinite = function(obj) { _.isFinite = function(obj) {
return _.isNumber(obj) && isFinite(obj); return isFinite(obj) && !isNaN(parseFloat(obj));
}; };
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
@ -994,9 +1089,35 @@
return value; return value;
}; };
_.constant = function(value) {
return function () {
return value;
};
};
_.property = function(key) {
return function(obj) {
return obj[key];
};
};
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
_.matches = function(attrs) {
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;
}
return true;
}
};
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iterator, context) {
for (var i = 0; i < n; i++) iterator.call(context, i); var accum = Array(Math.max(0, n));
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
return accum;
}; };
// Return a random integer between min and max (inclusive). // Return a random integer between min and max (inclusive).
@ -1005,9 +1126,12 @@
max = min; max = min;
min = 0; min = 0;
} }
return min + (0 | Math.random() * (max - min + 1)); return min + Math.floor(Math.random() * (max - min + 1));
}; };
// 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. // List of HTML entities for escaping.
var entityMap = { var entityMap = {
escape: { escape: {
@ -1015,8 +1139,7 @@
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#x27;', "'": '&#x27;'
'/': '&#x2F;'
} }
}; };
entityMap.unescape = _.invert(entityMap.escape); entityMap.unescape = _.invert(entityMap.escape);
@ -1037,17 +1160,17 @@
}; };
}); });
// If the value of the named property is a function then invoke it; // If the value of the named `property` is a function then invoke it with the
// otherwise, return it. // `object` as context; otherwise, return it.
_.result = function(object, property) { _.result = function(object, property) {
if (object == null) return null; if (object == null) return void 0;
var value = object[property]; var value = object[property];
return _.isFunction(value) ? value.call(object) : value; return _.isFunction(value) ? value.call(object) : value;
}; };
// Add your own custom functions to the Underscore object. // Add your own custom functions to the Underscore object.
_.mixin = function(obj) { _.mixin = function(obj) {
each(_.functions(obj), function(name){ each(_.functions(obj), function(name) {
var func = _[name] = obj[name]; var func = _[name] = obj[name];
_.prototype[name] = function() { _.prototype[name] = function() {
var args = [this._wrapped]; var args = [this._wrapped];
@ -1061,7 +1184,7 @@
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
_.uniqueId = function(prefix) { _.uniqueId = function(prefix) {
var id = idCounter++; var id = ++idCounter + '';
return prefix ? prefix + id : id; return prefix ? prefix + id : id;
}; };
@ -1096,6 +1219,7 @@
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { _.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
@ -1111,11 +1235,18 @@
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; }); .replace(escaper, function(match) { return '\\' + escapes[match]; });
source +=
escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : if (escape) {
interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
evaluate ? "';\n" + evaluate + "\n__p+='" : ''; }
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length; index = offset + match.length;
return match;
}); });
source += "';\n"; source += "';\n";
@ -1127,7 +1258,7 @@
source + "return __p;\n"; source + "return __p;\n";
try { try {
var render = new Function(settings.variable || 'obj', '_', source); render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;
@ -1197,4 +1328,16 @@
}); });
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}).call(this); }).call(this);

View File

@ -24,7 +24,7 @@
"js2xmlparser": "~0.1.0", "js2xmlparser": "~0.1.0",
"marked": "~0.3.1", "marked": "~0.3.1",
"taffydb": "https://github.com/hegemonic/taffydb/tarball/master", "taffydb": "https://github.com/hegemonic/taffydb/tarball/master",
"underscore": "~1.4.2", "underscore": "~1.6.0",
"wrench": "~1.3.9" "wrench": "~1.3.9"
}, },
"devDependencies": { "devDependencies": {