Unverified Commit bb9b5a91 authored by Jeremy Morrell's avatar Jeremy Morrell Committed by GitHub

Install devDependencies by default (#519)

Fixes #431 

Many users getting started with Heroku try to run a build step with webpack, gulp, etc only to find that it's in their devDependencies and not installed by default on Heroku. They then have to figure out how to tell Heroku to install these. Defaulting to installing everything makes for a smoother onboarding.

Changes the default behavior to install `devDependencies`, run the build step, and then prune the `devDependencies` once the build step is complete.
parent c9a02566
......@@ -2,6 +2,8 @@
## Master
- Install and prune devDependencies by default (#519)
## v118 (2018-02-02)
- Fix issue with `NODE_ENV` in CI (#513)
......
......@@ -211,6 +211,17 @@ cache_build() {
header "Caching build"
cache_build | output "$LOG_FILE"
prune_devdependencies() {
if $YARN; then
yarn_prune_devdependencies "$BUILD_DIR"
else
npm_prune_devdependencies "$BUILD_DIR"
fi
}
header "Pruning devDependencies"
prune_devdependencies | output "$LOG_FILE"
summarize_build() {
if $NODE_VERBOSE; then
list_dependencies "$BUILD_DIR"
......
......@@ -87,14 +87,34 @@ log_build_scripts() {
yarn_node_modules() {
local build_dir=${1:-}
local production=${YARN_PRODUCTION:-false}
echo "Installing node modules (yarn.lock)"
cd "$build_dir"
yarn install --frozen-lockfile --ignore-engines 2>&1
yarn install --production=$production --frozen-lockfile --ignore-engines 2>&1
}
yarn_prune_devdependencies() {
local build_dir=${1:-}
if [ "$NODE_ENV" == "test" ]; then
echo "Skipping because NODE_ENV is 'test'"
return 0
elif [ "$NODE_ENV" != "production" ]; then
echo "Skipping because NODE_ENV is not 'production'"
return 0
elif [ -n "$YARN_PRODUCTION" ] && [ "$YARN_PRODUCTION" != "true" ]; then
echo "Skipping because YARN_PRODUCTION is not 'true'"
return 0
else
cd "$build_dir"
yarn install --frozen-lockfile --ignore-engines --ignore-scripts --prefer-offline 2>&1
fi
}
npm_node_modules() {
local build_dir=${1:-}
local production=${NPM_CONFIG_PRODUCTION:-false}
if [ -e $build_dir/package.json ]; then
cd $build_dir
......@@ -106,7 +126,7 @@ npm_node_modules() {
else
echo "Installing node modules (package.json)"
fi
npm install --unsafe-perm --userconfig $build_dir/.npmrc 2>&1
npm install --production=$production --unsafe-perm --userconfig $build_dir/.npmrc 2>&1
else
echo "Skipping (no package.json)"
fi
......@@ -114,6 +134,7 @@ npm_node_modules() {
npm_rebuild() {
local build_dir=${1:-}
local production=${NPM_CONFIG_PRODUCTION:-false}
if [ -e $build_dir/package.json ]; then
cd $build_dir
......@@ -124,8 +145,32 @@ npm_rebuild() {
else
echo "Installing any new modules (package.json)"
fi
npm install --unsafe-perm --userconfig $build_dir/.npmrc 2>&1
npm install --production=$production --unsafe-perm --userconfig $build_dir/.npmrc 2>&1
else
echo "Skipping (no package.json)"
fi
}
npm_prune_devdependencies() {
local build_dir=${1:-}
local npm_version=$(npm --version)
if [ $NODE_ENV == "test" ]; then
echo "Skipping because NODE_ENV is 'test'"
return 0
elif [ $NODE_ENV != "production" ]; then
echo "Skipping because NODE_ENV is not 'production'"
return 0
elif [ -n "$NPM_CONFIG_PRODUCTION" ] && [ "$NPM_CONFIG_PRODUCTION" != "true" ]; then
echo "Skipping because NPM_CONFIG_PRODUCTION is not 'true'"
return 0
elif [ $npm_version == "5.3.0" ]; then
mcount "skip-prune-issue-npm-5.3.0"
echo "Skipping because npm 5.3.0 fails when running 'npm prune' due to a known issue"
echo "https://github.com/npm/npm/issues/17781"
return 0
else
cd "$build_dir"
npm prune --userconfig $build_dir/.npmrc 2>&1
fi
}
......@@ -16,7 +16,6 @@ platform="$os-$cpu"
export JQ="$BP_DIR/vendor/jq-$os"
create_default_env() {
export NPM_CONFIG_PRODUCTION=${NPM_CONFIG_PRODUCTION:-true}
export NPM_CONFIG_LOGLEVEL=${NPM_CONFIG_LOGLEVEL:-error}
export NODE_MODULES_CACHE=${NODE_MODULES_CACHE:-true}
export NODE_ENV=${NODE_ENV:-production}
......@@ -68,7 +67,7 @@ write_ci_profile() {
local bp_dir="$1"
local build_dir="$2"
write_profile "$1" "$2"
cp $bp_dir/ci-profile/* $build_dir/.profile.d/
cp $bp_dir/ci-profile/* $build_dir/.profile.d/
}
write_export() {
......
......@@ -122,8 +122,7 @@ fail_yarn_outdated() {
local log_file="$1"
local yarn_engine=$(read_json "$BUILD_DIR/package.json" ".engines.yarn")
if grep -qi 'error: unknown option .--frozen-lockfile' "$log_file"; then
echo "ran"
if grep -qi 'error .install. has been replaced with .add. to add new dependencies' "$log_file"; then
mcount "failures.outdated-yarn"
echo ""
warn "Outdated Yarn version: $yarn_engine
......
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository": {
"type": "git",
"url": "http://github.com/example/example.git"
},
"dependencies": {
"hashish": "*"
},
"license": "MIT",
"engines": {
"yarn": "1.4.0"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"test": "ls node_modules"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
hashish@*:
version "0.0.4"
resolved "https://registry.yarnpkg.com/hashish/-/hashish-0.0.4.tgz#6d60bc6ffaf711b6afd60e426d077988014e6554"
dependencies:
traverse ">=0.2.4"
lodash@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e"
traverse@>=0.2.4:
version "0.6.6"
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
......@@ -10,9 +10,12 @@
"hashish": "*"
},
"engines": {
"node": "~0.10.0"
"node": "8.x"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"test": "ls node_modules"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
Hashish
=======
Hashish is a node.js library for manipulating hash data structures.
It is distilled from the finest that ruby, perl, and haskell have to offer by
way of hash/map interfaces.
Hashish provides a chaining interface, where you can do:
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
Output:
a => 10
b => 20
Some functions and attributes in the chaining interface are terminal, like
`.items` or `.detect()`. They return values of their own instead of the chain
context.
Each function in the chainable interface is also attached to `Hash` in chainless
form:
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
Output:
{ a: 10, b: 20, c: 30, d: 40 }
In either case, the 'this' context of the function calls is the same object that
the chained functions return, so you can make nested chains.
Methods
=======
forEach(cb)
-----------
For each key/value in the hash, calls `cb(value, key)`.
map(cb)
-------
For each key/value in the hash, calls `cb(value, key)`.
The return value of `cb` is the new value at `key` in the resulting hash.
filter(cb)
----------
For each key/value in the hash, calls `cb(value, key)`.
The resulting hash omits key/value pairs where `cb` returned a falsy value.
detect(cb)
----------
Returns the first value in the hash for which `cb(value, key)` is non-falsy.
Order of hashes is not well-defined so watch out for that.
reduce(cb)
----------
Returns the accumulated value of a left-fold over the key/value pairs.
some(cb)
--------
Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy
value.
update(obj1, [obj2, obj3, ...])
-----------
Mutate the context hash, merging the key/value pairs from the passed objects
and overwriting keys from the context hash if the current `obj` has keys of
the same name. Falsy arguments are silently ignored.
updateAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `update()` but operate on an array directly.
merge(obj1, [obj2, obj3, ...])
----------
Merge the key/value pairs from the passed objects into the resultant hash
without modifying the context hash. Falsy arguments are silently ignored.
mergeAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `merge()` but operate on an array directly.
has(key)
--------
Return whether the hash has a key, `key`.
valuesAt(keys)
--------------
Return an Array with the values at the keys from `keys`.
tap(cb)
-------
Call `cb` with the present raw hash.
This function is chainable.
extract(keys)
-------------
Filter by including only those keys in `keys` in the resulting hash.
exclude(keys)
-------------
Filter by excluding those keys in `keys` in the resulting hash.
Attributes
==========
These are attributes in the chaining interface and functions in the `Hash.xxx`
interface.
keys
----
Return all the enumerable attribute keys in the hash.
values
------
Return all the enumerable attribute values in the hash.
compact
-------
Filter out values which are `=== undefined`.
clone
-----
Make a deep copy of the hash.
copy
----
Make a shallow copy of the hash.
length
------
Return the number of key/value pairs in the hash.
Note: use `Hash.size()` for non-chain mode.
size
----
Alias for `length` since `Hash.length` is masked by `Function.prototype`.
See Also
========
See also [creationix's pattern/hash](http://github.com/creationix/pattern),
which does a similar thing except with hash inputs and array outputs.
Installation
============
To install with [npm](http://github.com/isaacs/npm):
npm install hashish
To run the tests with [expresso](http://github.com/visionmedia/expresso):
expresso
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
module.exports = Hash;
var Traverse = require('traverse');
function Hash (hash, xs) {
if (Array.isArray(hash) && Array.isArray(xs)) {
var to = Math.min(hash.length, xs.length);
var acc = {};
for (var i = 0; i < to; i++) {
acc[hash[i]] = xs[i];
}
return Hash(acc);
}
if (hash === undefined) return Hash({});
var self = {
map : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
acc[key] = f.call(self, hash[key], key);
});
return Hash(acc);
},
forEach : function (f) {
Object.keys(hash).forEach(function (key) {
f.call(self, hash[key], key);
});
return self;
},
filter : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
if (f.call(self, hash[key], key)) {
acc[key] = hash[key];
}
});
return Hash(acc);
},
detect : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) {
return hash[key];
}
}
return undefined;
},
reduce : function (f, acc) {
var keys = Object.keys(hash);
if (acc === undefined) acc = keys.shift();
keys.forEach(function (key) {
acc = f.call(self, acc, hash[key], key);
});
return acc;
},
some : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) return true;
}
return false;
},
update : function (obj) {
if (arguments.length > 1) {
self.updateAll([].slice.call(arguments));
}
else {
Object.keys(obj).forEach(function (key) {
hash[key] = obj[key];
});
}
return self;
},
updateAll : function (xs) {
xs.filter(Boolean).forEach(function (x) {
self.update(x);
});
return self;
},
merge : function (obj) {
if (arguments.length > 1) {
return self.copy.updateAll([].slice.call(arguments));
}
else {
return self.copy.update(obj);
}
},
mergeAll : function (xs) {
return self.copy.updateAll(xs);
},
has : function (key) { // only operates on enumerables
return Array.isArray(key)
? key.every(function (k) { return self.has(k) })
: self.keys.indexOf(key.toString()) >= 0;
},
valuesAt : function (keys) {
return Array.isArray(keys)
? keys.map(function (key) { return hash[key] })
: hash[keys]
;
},
tap : function (f) {
f.call(self, hash);
return self;
},
extract : function (keys) {
var acc = {};
keys.forEach(function (key) {
acc[key] = hash[key];
});
return Hash(acc);
},
exclude : function (keys) {
return self.filter(function (_, key) {
return keys.indexOf(key) < 0
});
},
end : hash,
items : hash
};
var props = {
keys : function () { return Object.keys(hash) },
values : function () {
return Object.keys(hash).map(function (key) { return hash[key] });
},
compact : function () {
return self.filter(function (x) { return x !== undefined });
},
clone : function () { return Hash(Hash.clone(hash)) },
copy : function () { return Hash(Hash.copy(hash)) },
length : function () { return Object.keys(hash).length },
size : function () { return self.length }
};
if (Object.defineProperty) {
// es5-shim has an Object.defineProperty but it throws for getters
try {
for (var key in props) {
Object.defineProperty(self, key, { get : props[key] });
}
}
catch (err) {
for (var key in props) {
if (key !== 'clone' && key !== 'copy' && key !== 'compact') {
// ^ those keys use Hash() so can't call them without
// a stack overflow
self[key] = props[key]();
}
}
}
}
else if (self.__defineGetter__) {
for (var key in props) {
self.__defineGetter__(key, props[key]);
}
}
else {
// non-lazy version for browsers that suck >_<
for (var key in props) {
self[key] = props[key]();
}
}
return self;
};
// deep copy
Hash.clone = function (ref) {
return Traverse.clone(ref);
};
// shallow copy
Hash.copy = function (ref) {
var hash = { __proto__ : ref.__proto__ };
Object.keys(ref).forEach(function (key) {
hash[key] = ref[key];
});
return hash;
};
Hash.map = function (ref, f) {
return Hash(ref).map(f).items;
};
Hash.forEach = function (ref, f) {
Hash(ref).forEach(f);
};
Hash.filter = function (ref, f) {
return Hash(ref).filter(f).items;
};
Hash.detect = function (ref, f) {
return Hash(ref).detect(f);
};
Hash.reduce = function (ref, f, acc) {
return Hash(ref).reduce(f, acc);
};
Hash.some = function (ref, f) {
return Hash(ref).some(f);
};
Hash.update = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.update.apply(hash, args).items;
};
Hash.merge = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.merge.apply(hash, args).items;
};
Hash.has = function (ref, key) {
return Hash(ref).has(key);
};
Hash.valuesAt = function (ref, keys) {
return Hash(ref).valuesAt(keys);
};
Hash.tap = function (ref, f) {
return Hash(ref).tap(f).items;
};
Hash.extract = function (ref, keys) {
return Hash(ref).extract(keys).items;
};
Hash.exclude = function (ref, keys) {
return Hash(ref).exclude(keys).items;
};
Hash.concat = function (xs) {
var hash = Hash({});
xs.forEach(function (x) { hash.update(x) });
return hash.items;
};
Hash.zip = function (xs, ys) {
return Hash(xs, ys).items;
};
// .length is already defined for function prototypes
Hash.size = function (ref) {
return Hash(ref).size;
};
Hash.compact = function (ref) {
return Hash(ref).compact.items;
};
{
"_from": "hashish@*",
"_id": "hashish@0.0.4",
"_inBundle": false,
"_integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
"_location": "/hashish",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "hashish@*",
"name": "hashish",
"escapedName": "hashish",
"rawSpec": "*",
"saveSpec": null,
"fetchSpec": "*"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
"_shasum": "6d60bc6ffaf711b6afd60e426d077988014e6554",
"_spec": "hashish@*",
"_where": "/Users/jmorrell/workspace/heroku-buildpack-nodejs/test/fixtures/dependencies-modules-checked-in-with-devdependencies",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/node-hashish/issues"
},
"bundleDependencies": false,
"dependencies": {
"traverse": ">=0.2.4"
},
"deprecated": false,
"description": "Hash data structure manipulation functions",
"devDependencies": {
"expresso": ">=0.6.0"
},
"engine": [
"node >=0.2.0"
],
"engines": {
"node": "*"
},
"homepage": "https://github.com/substack/node-hashish#readme",
"keywords": [
"hash",
"object",
"convenience",
"manipulation",
"data structure"
],
"license": "MIT/X11",
"main": "./index.js",
"name": "hashish",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/substack/node-hashish.git"
},
"scripts": {
"test": "expresso"
},
"version": "0.0.4"
}
var Hash = require('hashish');
var assert = require('assert');
exports.map = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).map(function (v) { return v + 1 }).items;
var hash = Hash.map(ref, function (v) { return v + 1 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 2, b : 3 });
assert.deepEqual(hash, { a : 2, b : 3 });
};
exports['cloned map'] = function () {
var ref = { foo : [1,2], bar : [4,5] };
var hash = Hash(ref).clone.map(
function (v) { v.unshift(v[0] - 1); return v }
).items;
assert.deepEqual(ref.foo, [1,2]);
assert.deepEqual(ref.bar, [4,5]);
assert.deepEqual(hash.foo, [0,1,2]);
assert.deepEqual(hash.bar, [3,4,5]);
};
exports.forEach = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var xs = [];
Hash(ref).forEach(function (x, i) {
xs.push([ i, x ]);
});
assert.eql(
xs.map(function (x) { return x[0] }).sort(),
[ '1337', 'a', 'b', 'c' ]
);
assert.eql(
xs.map(function (x) { return x[1] }).sort(),
[ 2, 5, 7, 'leet' ]
);
var ys = [];
Hash.forEach(ref, function (x, i) {
ys.push([ i, x ]);
});
assert.eql(xs.sort(), ys.sort());
};
exports.filter_items = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var items = Hash(ref).filter(function (v, k) {
return v > 5 || k > 5
}).items;
var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 });
assert.deepEqual(items, { 1337 : 'leet', c : 7 });
assert.deepEqual(hash, { 1337 : 'leet', c : 7 });
assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' });
assert.equal(Hash(ref).length, 4);
};
exports.detect = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
var gt6hh = hh.detect(function (x) { return x > 6 });
assert.ok(gt6hh == 7 || gt6hh == 8);
var gt6h = Hash.detect(h, function (x) { return x > 6 });
assert.ok(gt6h == 7 || gt6h == 8);
assert.equal(hh.detect(function (x) { return x > 100 }), undefined);
};
exports.reduce = function () {
var ref = { foo : [1,2], bar : [4,5] };
var sum1 = Hash(ref).reduce(function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum1, 4);
var sum2 = Hash.reduce(ref, function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum2, 4);
};
exports.some = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
assert.ok(Hash.some(h, function (x) { return x > 7 }));
assert.ok(Hash.some(h, function (x) { return x < 6 }));
assert.ok(!Hash.some(h, function (x) { return x > 10 }));
assert.ok(!Hash.some(h, function (x) { return x < 0 }));
assert.ok(hh.some(function (x) { return x > 7 }));
assert.ok(hh.some(function (x) { return x < 6 }));
assert.ok(!hh.some(function (x) { return x > 10 }));
assert.ok(!hh.some(function (x) { return x < 0 }));
};
exports.update = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).clone.update({ c : 3, a : 0 }).items;
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 0, b : 2, c : 3 });
var hash = Hash.update(ref, { c : 3, a : 0 });
assert.deepEqual(ref, hash);
assert.deepEqual(hash, { a : 0, b : 2, c : 3 });
var ref2 = {a: 1};
var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.merge = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).merge({ b : 3, c : 3.14 }).items;
var hash = Hash.merge(ref, { b : 3, c : 3.14 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 1, b : 3, c : 3.14 });
assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 });
var ref2 = { a : 1 };
var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.has = function () {
var h = { a : 4, b : 5 };
var hh = Hash(h);
assert.ok(hh.has('a'));
assert.equal(hh.has('c'), false);
assert.ok(hh.has(['a','b']));
assert.equal(hh.has(['a','b','c']), false);
assert.ok(Hash.has(h, 'a'));
assert.equal(Hash.has(h, 'c'), false);
assert.ok(Hash.has(h, ['a','b']));
assert.equal(Hash.has(h, ['a','b','c']), false);
};
exports.valuesAt = function () {
var h = { a : 4, b : 5, c : 6 };
assert.equal(Hash(h).valuesAt('a'), 4);
assert.equal(Hash(h).valuesAt(['a'])[0], 4);
assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]);
assert.equal(Hash.valuesAt(h, 'a'), 4);
assert.deepEqual(Hash.valuesAt(h, ['a']), [4]);
assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]);
};
exports.tap = function () {
var h = { a : 4, b : 5, c : 6 };
var hh = Hash(h);
hh.tap(function (x) {
assert.ok(this === hh)
assert.eql(x, h);
});
Hash.tap(h, function (x) {
assert.eql(
Object.keys(this).sort(),
Object.keys(hh).sort()
);
assert.eql(x, h);
});
};
exports.extract = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.extract(['a','b']);
assert.equal(extracted.length, 2);
assert.deepEqual(extracted.items, { a : 1, b : 2 });
};
exports.exclude = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.exclude(['a','b']);
assert.equal(extracted.length, 1);
assert.deepEqual(extracted.items, { c : 3 });
};
exports.concat = function () {
var ref1 = { a : 1, b : 2 };
var ref2 = { foo : 100, bar : 200 };
var ref3 = { b : 3, c : 4, bar : 300 };
assert.deepEqual(
Hash.concat([ ref1, ref2 ]),
{ a : 1, b : 2, foo : 100, bar : 200 }
);
assert.deepEqual(
Hash.concat([ ref1, ref2, ref3 ]),
{ a : 1, b : 3, c : 4, foo : 100, bar : 300 }
);
};
exports.zip = function () {
var xs = ['a','b','c'];
var ys = [1,2,3,4];
var h = Hash(xs,ys);
assert.equal(h.length, 3);
assert.deepEqual(h.items, { a : 1, b : 2, c : 3 });
var zipped = Hash.zip(xs,ys);
assert.deepEqual(zipped, { a : 1, b : 2, c : 3 });
};
exports.length = function () {
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3);
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3);
assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3);
};
exports.compact = function () {
var hash = {
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
};
var compacted = Hash(hash).compact;
assert.deepEqual(
{
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
},
hash, 'compact modified the hash'
);
assert.deepEqual(
compacted.items,
{
a : 1,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
}
);
var h = Hash.compact(hash);
assert.deepEqual(h, compacted.items);
};
var Hash = require('hashish');
var assert = require('assert');
var vm = require('vm');
var fs = require('fs');
var src = fs.readFileSync(__dirname + '/../index.js', 'utf8');
exports.defineGetter = function () {
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : undefined,
},
require : require,
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
var times = 0;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
times ++;
return Object.__defineGetter__.apply(this, arguments);
};
assert.equal(vm.runInNewContext('Object.defineProperty', context), null);
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.ok(times > 5);
};
exports.defineProperty = function () {
var times = 0;
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : function (prop) {
times ++;
if (prop.get) throw new TypeError('engine does not support')
assert.fail('should have asserted by now');
},
},
require : require
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
assert.fail('getter called when a perfectly good'
+ ' defineProperty was available'
);
};
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.equal(times, 1);
};
Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js 1.5.2, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
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
# Lo-Dash v2.4.2
A utility library delivering consistency, [customization](https://lodash.com/custom-builds), [performance](https://lodash.com/benchmarks), & [extras](https://lodash.com/#features).
## Download
Check out our [wiki]([https://github.com/lodash/lodash/wiki/build-differences]) for details over the differences between builds.
* Modern builds perfect for newer browsers/environments:<br>
[Development](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.js) &
[Production](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.min.js)
* Compatibility builds for older environment support too:<br>
[Development](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.compat.js) &
[Production](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.compat.min.js)
* Underscore builds to use as a drop-in replacement:<br>
[Development](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.underscore.js) &
[Production](https://raw.github.com/lodash/lodash/2.4.2/dist/lodash.underscore.min.js)
CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](https://lodash.com/custom-builds) with only the features needed.
Love modules? We’ve got you covered with [lodash-amd](https://npmjs.org/package/lodash-amd), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method.
## Dive in
There’s plenty of **[documentation](https://lodash.com/docs)**, [unit tests](https://lodash.com/tests), & [benchmarks](https://lodash.com/benchmarks).<br>
Check out <a href="http://devdocs.io/lodash/">DevDocs</a> as a fast, organized, & searchable interface for our documentation.
The full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).<br>
A list of upcoming features is available on our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).
## Installation & usage
In browsers:
```html
<script src="lodash.js"></script>
```
Using [`npm`](http://npmjs.org/):
```bash
npm i --save lodash
{sudo} npm i -g lodash
npm ln lodash
```
In [Node.js](http://nodejs.org/) & [Ringo](http://ringojs.org/):
```js
var _ = require('lodash');
// or as Underscore
var _ = require('lodash/dist/lodash.underscore');
```
**Notes:**
* Don’t assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL
* If Lo-Dash is installed globally, run [`npm ln lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory *before* requiring it
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('lodash.js');
```
In an AMD loader:
```js
require({
'packages': [
{ 'name': 'lodash', 'location': 'path/to/lodash', 'main': 'lodash' }
]
},
['lodash'], function(_) {
console.log(_.VERSION);
});
```
## Resources
* Podcasts
- [JavaScript Jabber](http://javascriptjabber.com/079-jsj-lo-dash-with-john-david-dalton/)
* Posts
- [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
- [Custom builds in Lo-Dash 2.0](http://kitcambridge.be/blog/custom-builds-in-lo-dash-2-dot-0/)
* Videos
- [Introduction](https://vimeo.com/44154599)
- [Origins](https://vimeo.com/44154600)
- [Optimizations & builds](https://vimeo.com/44154601)
- [Native method use](https://vimeo.com/48576012)
- [Testing](https://vimeo.com/45865290)
- [CascadiaJS ’12](http://www.youtube.com/watch?v=dpPy4f_SeEk)
A list of other community created podcasts, posts, & videos is available on our [wiki](https://github.com/lodash/lodash/wiki/Resources).
## Features
* AMD loader support ([curl](https://github.com/cujojs/curl), [dojo](http://dojotoolkit.org/), [requirejs](http://requirejs.org/), etc.)
* [_(…)](https://lodash.com/docs#_) supports intuitive chaining
* [_.at](https://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](https://lodash.com/docs#bindKey) for binding [*“lazy”*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods
* [_.clone](https://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects
* [_.cloneDeep](https://lodash.com/docs#cloneDeep) for deep cloning arrays & objects
* [_.constant](https://lodash.com/docs#constant) & [_.property](https://lodash.com/docs#property) function generators for composing functions
* [_.contains](https://lodash.com/docs#contains) accepts a `fromIndex`
* [_.create](https://lodash.com/docs#create) for easier object inheritance
* [_.createCallback](https://lodash.com/docs#createCallback) for extending callbacks in methods & mixins
* [_.curry](https://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/2013/07/06/why-curry-helps/) functions
* [_.debounce](https://lodash.com/docs#debounce) & [_.throttle](https://lodash.com/docs#throttle) accept additional `options` for more control
* [_.findIndex](https://lodash.com/docs#findIndex) & [_.findKey](https://lodash.com/docs#findKey) for finding indexes & keys
* [_.forEach](https://lodash.com/docs#forEach) is chainable & supports exiting early
* [_.forIn](https://lodash.com/docs#forIn) for iterating own & inherited properties
* [_.forOwn](https://lodash.com/docs#forOwn) for iterating own properties
* [_.isPlainObject](https://lodash.com/docs#isPlainObject) for checking if values are created by `Object`
* [_.mapValues](https://lodash.com/docs#mapValues) for [mapping](https://lodash.com/docs#map) values to an object
* [_.memoize](https://lodash.com/docs#memoize) exposes the `cache` of memoized functions
* [_.merge](https://lodash.com/docs#merge) for a deep [_.extend](https://lodash.com/docs#extend)
* [_.noop](https://lodash.com/docs#noop) for function placeholders
* [_.now](https://lodash.com/docs#now) as a cross-browser `Date.now` alternative
* [_.parseInt](https://lodash.com/docs#parseInt) for consistent behavior
* [_.pull](https://lodash.com/docs#pull) & [_.remove](https://lodash.com/docs#remove) for mutating arrays
* [_.random](https://lodash.com/docs#random) supports returning floating-point numbers
* [_.runInContext](https://lodash.com/docs#runInContext) for easier mocking
* [_.sortBy](https://lodash.com/docs#sortBy) supports sorting by multiple properties
* [_.support](https://lodash.com/docs#support) for flagging environment features
* [_.template](https://lodash.com/docs#template) supports [*“imports”*](https://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals)
* [_.transform](https://lodash.com/docs#transform) as a powerful alternative to [_.reduce](https://lodash.com/docs#reduce) for transforming objects
* [_.where](https://lodash.com/docs#where) supports deep object comparisons
* [_.xor](https://lodash.com/docs#xor) as a companion to [_.difference](https://lodash.com/docs#difference), [_.intersection](https://lodash.com/docs#intersection), & [_.union](https://lodash.com/docs#union)
* [_.zip](https://lodash.com/docs#zip) is capable of unzipping values
* [_.omit](https://lodash.com/docs#omit), [_.pick](https://lodash.com/docs#pick), &
[more](https://lodash.com/docs "_.assign, _.clone, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept callbacks
* [_.contains](https://lodash.com/docs#contains), [_.toArray](https://lodash.com/docs#toArray), &
[more](https://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.forEachRight, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.size, _.some, _.sortBy, _.where") accept strings
* [_.filter](https://lodash.com/docs#filter), [_.map](https://lodash.com/docs#map), &
[more](https://lodash.com/docs "_.countBy, _.every, _.find, _.findKey, _.findLast, _.findLastIndex, _.findLastKey, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* & *“_.where”* shorthands
* [_.findLast](https://lodash.com/docs#findLast), [_.findLastIndex](https://lodash.com/docs#findLastIndex), &
[more](https://lodash.com/docs "_.findLastKey, _.forEachRight, _.forInRight, _.forOwnRight, _.partialRight") right-associative methods
## Support
Tested in Chrome 5~31, Firefox 2~25, IE 6-11, Opera 9.25-17, Safari 3-7, Node.js 0.6.21-0.10.22, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5.
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* @license
* Lo-Dash 2.4.2 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Build: `lodash -o ./dist/lodash.compat.js`
*/
;(function(){function n(n,r,e){for(var t=(e||0)-1,o=n?n.length:0;++t<o;)if(n[t]===r)return t;return-1}function r(r,e){var t=typeof e;if(r=r.cache,"boolean"==t||null==e)return r[e]?0:-1;"number"!=t&&"string"!=t&&(t="object");var o="number"==t?e:m+e;return r=(r=r[t])&&r[o],"object"==t?r&&n(r,e)>-1?0:-1:r?0:-1}function e(n){var r=this.cache,e=typeof n;if("boolean"==e||null==n)r[n]=!0;else{"number"!=e&&"string"!=e&&(e="object");var t="number"==e?n:m+n,o=r[e]||(r[e]={});"object"==e?(o[t]||(o[t]=[])).push(n):o[t]=!0;
}}function t(n){return n.charCodeAt(0)}function o(n,r){for(var e=n.criteria,t=r.criteria,o=-1,u=e.length;++o<u;){var a=e[o],i=t[o];if(a!==i){if(a>i||"undefined"==typeof a)return 1;if(a<i||"undefined"==typeof i)return-1}}return n.index-r.index}function u(n){var r=-1,t=n.length,o=n[0],u=n[t/2|0],a=n[t-1];if(o&&"object"==typeof o&&u&&"object"==typeof u&&a&&"object"==typeof a)return!1;var i=l();i["false"]=i["null"]=i["true"]=i.undefined=!1;var c=l();for(c.array=n,c.cache=i,c.push=e;++r<t;)c.push(n[r]);
return c}function a(n){return"\\"+Z[n]}function i(){return v.pop()||[]}function l(){return y.pop()||{array:null,cache:null,criteria:null,"false":!1,index:0,"null":!1,number:null,object:null,push:null,string:null,"true":!1,undefined:!1,value:null}}function c(n){return"function"!=typeof n.toString&&"string"==typeof(n+"")}function f(n){n.length=0,v.length<w&&v.push(n)}function s(n){var r=n.cache;r&&s(r),n.array=n.cache=n.criteria=n.object=n.number=n.string=n.value=null,y.length<w&&y.push(n)}function p(n,r,e){
r||(r=0),"undefined"==typeof e&&(e=n?n.length:0);for(var t=-1,o=e-r||0,u=Array(o<0?0:o);++t<o;)u[t]=n[r+t];return u}function g(e){function v(n){return n&&"object"==typeof n&&!st(n)&&Ke.call(n,"__wrapped__")?n:new y(n)}function y(n,r){this.__chain__=!!r,this.__wrapped__=n}function w(n){function r(){if(t){var n=p(t);Ue.apply(n,arguments)}if(this instanceof r){var u=rn(e.prototype),a=e.apply(u,n||arguments);return Fn(a)?a:u}return e.apply(o,n||arguments)}var e=n[0],t=n[2],o=n[4];return ft(r,n),r}function Z(n,r,e,t,o){
if(e){var u=e(n);if("undefined"!=typeof u)return u}var a=Fn(n);if(!a)return n;var l=$e.call(n);if(!G[l]||!lt.nodeClass&&c(n))return n;var s=at[l];switch(l){case H:case W:return new s(+n);case K:case V:return new s(n);case M:return u=s(n.source,O.exec(n)),u.lastIndex=n.lastIndex,u}var g=st(n);if(r){var h=!t;t||(t=i()),o||(o=i());for(var v=t.length;v--;)if(t[v]==n)return o[v];u=g?s(n.length):{}}else u=g?p(n):xt({},n);return g&&(Ke.call(n,"index")&&(u.index=n.index),Ke.call(n,"input")&&(u.input=n.input)),
r?(t.push(n),o.push(u),(g?wt:Ct)(n,function(n,a){u[a]=Z(n,r,e,t,o)}),h&&(f(t),f(o)),u):u}function rn(n,r){return Fn(n)?Xe(n):{}}function en(n,r,e){if("function"!=typeof n)return ue;if("undefined"==typeof r||!("prototype"in n))return n;var t=n.__bindData__;if("undefined"==typeof t&&(lt.funcNames&&(t=!n.name),t=t||!lt.funcDecomp,!t)){var o=qe.call(n);lt.funcNames||(t=!S.test(o)),t||(t=N.test(o),ft(n,t))}if(t===!1||t!==!0&&1&t[1])return n;switch(e){case 1:return function(e){return n.call(r,e)};case 2:
return function(e,t){return n.call(r,e,t)};case 3:return function(e,t,o){return n.call(r,e,t,o)};case 4:return function(e,t,o,u){return n.call(r,e,t,o,u)}}return qr(n,r)}function tn(n){function r(){var n=l?a:this;if(o){var h=p(o);Ue.apply(h,arguments)}if((u||f)&&(h||(h=p(arguments)),u&&Ue.apply(h,u),f&&h.length<i))return t|=16,tn([e,s?t:-4&t,h,null,a,i]);if(h||(h=arguments),c&&(e=n[g]),this instanceof r){n=rn(e.prototype);var v=e.apply(n,h);return Fn(v)?v:n}return e.apply(n,h)}var e=n[0],t=n[1],o=n[2],u=n[3],a=n[4],i=n[5],l=1&t,c=2&t,f=4&t,s=8&t,g=e;
return ft(r,n),r}function on(e,t){var o=-1,a=yn(),i=e?e.length:0,l=i>=_&&a===n,c=[];if(l){var f=u(t);f?(a=r,t=f):l=!1}for(;++o<i;){var p=e[o];a(t,p)<0&&c.push(p)}return l&&s(t),c}function an(n,r,e,t){for(var o=(t||0)-1,u=n?n.length:0,a=[];++o<u;){var i=n[o];if(i&&"object"==typeof i&&"number"==typeof i.length&&(st(i)||_n(i))){r||(i=an(i,r,e));var l=-1,c=i.length,f=a.length;for(a.length+=c;++l<c;)a[f++]=i[l]}else e||a.push(i)}return a}function ln(n,r,e,t,o,u){if(e){var a=e(n,r);if("undefined"!=typeof a)return!!a;
}if(n===r)return 0!==n||1/n==1/r;var l=typeof n,s=typeof r;if(n===n&&(!n||!Y[l])&&(!r||!Y[s]))return!1;if(null==n||null==r)return n===r;var p=$e.call(n),g=$e.call(r);if(p==F&&(p=U),g==F&&(g=U),p!=g)return!1;switch(p){case H:case W:return+n==+r;case K:return n!=+n?r!=+r:0==n?1/n==1/r:n==+r;case M:case V:return n==Ae(r)}var v=p==B;if(!v){var y=Ke.call(n,"__wrapped__"),b=Ke.call(r,"__wrapped__");if(y||b)return ln(y?n.__wrapped__:n,b?r.__wrapped__:r,e,t,o,u);if(p!=U||!lt.nodeClass&&(c(n)||c(r)))return!1;
var d=!lt.argsObject&&_n(n)?Oe:n.constructor,m=!lt.argsObject&&_n(r)?Oe:r.constructor;if(d!=m&&!($n(d)&&d instanceof d&&$n(m)&&m instanceof m)&&"constructor"in n&&"constructor"in r)return!1}var _=!o;o||(o=i()),u||(u=i());for(var w=o.length;w--;)if(o[w]==n)return u[w]==r;var x=0;if(a=!0,o.push(n),u.push(r),v){if(w=n.length,x=r.length,a=x==w,a||t)for(;x--;){var j=w,k=r[x];if(t)for(;j--&&!(a=ln(n[j],k,e,t,o,u)););else if(!(a=ln(n[x],k,e,t,o,u)))break}}else kt(r,function(r,i,l){return Ke.call(l,i)?(x++,
a=Ke.call(n,i)&&ln(n[i],r,e,t,o,u)):h}),a&&!t&&kt(n,function(n,r,e){return Ke.call(e,r)?a=--x>-1:h});return o.pop(),u.pop(),_&&(f(o),f(u)),a}function cn(n,r,e,t,o){(st(r)?or:Ct)(r,function(r,u){var a,i,l=r,c=n[u];if(r&&((i=st(r))||Pt(r))){for(var f=t.length;f--;)if(a=t[f]==r){c=o[f];break}if(!a){var s;e&&(l=e(c,r),(s="undefined"!=typeof l)&&(c=l)),s||(c=i?st(c)?c:[]:Pt(c)?c:{}),t.push(r),o.push(c),s||cn(c,r,e,t,o)}}else e&&(l=e(c,r),"undefined"==typeof l&&(l=r)),"undefined"!=typeof l&&(c=l);n[u]=c;
})}function fn(n,r){return n+We(ut()*(r-n+1))}function sn(e,t,o){var a=-1,l=yn(),c=e?e.length:0,p=[],g=!t&&c>=_&&l===n,h=o||g?i():p;if(g){var v=u(h);l=r,h=v}for(;++a<c;){var y=e[a],b=o?o(y,a,e):y;(t?!a||h[h.length-1]!==b:l(h,b)<0)&&((o||g)&&h.push(b),p.push(y))}return g?(f(h.array),s(h)):o&&f(h),p}function pn(n){return function(r,e,t){var o={};if(e=v.createCallback(e,t,3),st(r))for(var u=-1,a=r.length;++u<a;){var i=r[u];n(o,i,e(i,u,r),r)}else wt(r,function(r,t,u){n(o,r,e(r,t,u),u)});return o}}function gn(n,r,e,t,o,u){
var a=1&r,i=2&r,l=4&r,c=16&r,f=32&r;if(!i&&!$n(n))throw new Ie;c&&!e.length&&(r&=-17,c=e=!1),f&&!t.length&&(r&=-33,f=t=!1);var s=n&&n.__bindData__;if(s&&s!==!0)return s=p(s),s[2]&&(s[2]=p(s[2])),s[3]&&(s[3]=p(s[3])),!a||1&s[1]||(s[4]=o),!a&&1&s[1]&&(r|=8),!l||4&s[1]||(s[5]=u),c&&Ue.apply(s[2]||(s[2]=[]),e),f&&Je.apply(s[3]||(s[3]=[]),t),s[1]|=r,gn.apply(null,s);var g=1==r||17===r?w:tn;return g([n,r,e,t,o,u])}function hn(){X.shadowedProps=D,X.array=X.bottom=X.loop=X.top="",X.init="iterable",X.useHas=!0;
for(var n,r=0;n=arguments[r];r++)for(var e in n)X[e]=n[e];var t=X.args;X.firstArg=/^[^,]+/.exec(t)[0];var o=Ce("baseCreateCallback, errorClass, errorProto, hasOwnProperty, indicatorObject, isArguments, isArray, isString, keys, objectProto, objectTypes, nonEnumProps, stringClass, stringProto, toString","return function("+t+") {\n"+ct(X)+"\n}");return o(en,q,Ne,Ke,d,_n,st,zn,X.keys,Re,Y,it,V,Te,$e)}function vn(n){return bt[n]}function yn(){var r=(r=v.indexOf)===Cr?n:r;return r}function bn(n){return"function"==typeof n&&Fe.test(n);
}function dn(n){var r,e;return!n||$e.call(n)!=U||(r=n.constructor,$n(r)&&!(r instanceof r))||!lt.argsClass&&_n(n)||!lt.nodeClass&&c(n)?!1:lt.ownLast?(kt(n,function(n,r,t){return e=Ke.call(t,r),!1}),e!==!1):(kt(n,function(n,r){e=r}),"undefined"==typeof e||Ke.call(n,e))}function mn(n){return dt[n]}function _n(n){return n&&"object"==typeof n&&"number"==typeof n.length&&$e.call(n)==F||!1}function wn(n,r,e,t){return"boolean"!=typeof r&&null!=r&&(t=e,e=r,r=!1),Z(n,r,"function"==typeof e&&en(e,t,1))}function xn(n,r,e){
return Z(n,!0,"function"==typeof r&&en(r,e,1))}function jn(n,r){var e=rn(n);return r?xt(e,r):e}function kn(n,r,e){var t;return r=v.createCallback(r,e,3),Ct(n,function(n,e,o){return r(n,e,o)?(t=e,!1):h}),t}function Cn(n,r,e){var t;return r=v.createCallback(r,e,3),En(n,function(n,e,o){return r(n,e,o)?(t=e,!1):h}),t}function Pn(n,r,e){var t=[];kt(n,function(n,r){t.push(r,n)});var o=t.length;for(r=en(r,e,3);o--&&r(t[o--],t[o],n)!==!1;);return n}function En(n,r,e){var t=gt(n),o=t.length;for(r=en(r,e,3);o--;){
var u=t[o];if(r(n[u],u,n)===!1)break}return n}function On(n){var r=[];return kt(n,function(n,e){$n(n)&&r.push(e)}),r.sort()}function Sn(n,r){return n?Ke.call(n,r):!1}function An(n){for(var r=-1,e=gt(n),t=e.length,o={};++r<t;){var u=e[r];o[n[u]]=u}return o}function In(n){return n===!0||n===!1||n&&"object"==typeof n&&$e.call(n)==H||!1}function Ln(n){return n&&"object"==typeof n&&$e.call(n)==W||!1}function Nn(n){return n&&1===n.nodeType||!1}function Rn(n){var r=!0;if(!n)return r;var e=$e.call(n),t=n.length;
return e==B||e==V||(lt.argsClass?e==F:_n(n))||e==U&&"number"==typeof t&&$n(n.splice)?!t:(Ct(n,function(){return r=!1}),r)}function Tn(n,r,e,t){return ln(n,r,"function"==typeof e&&en(e,t,2))}function Dn(n){return Ze(n)&&!nt(parseFloat(n))}function $n(n){return"function"==typeof n}function Fn(n){return!(!n||!Y[typeof n])}function Bn(n){return Wn(n)&&n!=+n}function Hn(n){return null===n}function Wn(n){return"number"==typeof n||n&&"object"==typeof n&&$e.call(n)==K||!1}function qn(n){return n&&Y[typeof n]&&$e.call(n)==M||!1;
}function zn(n){return"string"==typeof n||n&&"object"==typeof n&&$e.call(n)==V||!1}function Kn(n){return"undefined"==typeof n}function Un(n,r,e){var t={};return r=v.createCallback(r,e,3),Ct(n,function(n,e,o){t[e]=r(n,e,o)}),t}function Mn(n){var r=arguments,e=2;if(!Fn(n))return n;if("number"!=typeof r[2]&&(e=r.length),e>3&&"function"==typeof r[e-2])var t=en(r[--e-1],r[e--],2);else e>2&&"function"==typeof r[e-1]&&(t=r[--e]);for(var o=p(arguments,1,e),u=-1,a=i(),l=i();++u<e;)cn(n,o[u],t,a,l);return f(a),
f(l),n}function Vn(n,r,e){var t={};if("function"!=typeof r){var o=[];kt(n,function(n,r){o.push(r)}),o=on(o,an(arguments,!0,!1,1));for(var u=-1,a=o.length;++u<a;){var i=o[u];t[i]=n[i]}}else r=v.createCallback(r,e,3),kt(n,function(n,e,o){r(n,e,o)||(t[e]=n)});return t}function Gn(n){for(var r=-1,e=gt(n),t=e.length,o=we(t);++r<t;){var u=e[r];o[r]=[u,n[u]]}return o}function Jn(n,r,e){var t={};if("function"!=typeof r)for(var o=-1,u=an(arguments,!0,!1,1),a=Fn(n)?u.length:0;++o<a;){var i=u[o];i in n&&(t[i]=n[i]);
}else r=v.createCallback(r,e,3),kt(n,function(n,e,o){r(n,e,o)&&(t[e]=n)});return t}function Qn(n,r,e,t){var o=st(n);if(null==e)if(o)e=[];else{var u=n&&n.constructor,a=u&&u.prototype;e=rn(a)}return r&&(r=v.createCallback(r,t,4),(o?wt:Ct)(n,function(n,t,o){return r(e,n,t,o)})),e}function Xn(n){for(var r=-1,e=gt(n),t=e.length,o=we(t);++r<t;)o[r]=n[e[r]];return o}function Yn(n){var r=arguments,e=-1,t=an(r,!0,!1,1),o=r[2]&&r[2][r[1]]===n?1:t.length,u=we(o);for(lt.unindexedChars&&zn(n)&&(n=n.split(""));++e<o;)u[e]=n[t[e]];
return u}function Zn(n,r,e){var t=-1,o=yn(),u=n?n.length:0,a=!1;return e=(e<0?et(0,u+e):e)||0,st(n)?a=o(n,r,e)>-1:"number"==typeof u?a=(zn(n)?n.indexOf(r,e):o(n,r,e))>-1:wt(n,function(n){return++t<e?h:!(a=n===r)}),a}function nr(n,r,e){var t=!0;if(r=v.createCallback(r,e,3),st(n))for(var o=-1,u=n.length;++o<u&&(t=!!r(n[o],o,n)););else wt(n,function(n,e,o){return t=!!r(n,e,o)});return t}function rr(n,r,e){var t=[];if(r=v.createCallback(r,e,3),st(n))for(var o=-1,u=n.length;++o<u;){var a=n[o];r(a,o,n)&&t.push(a);
}else wt(n,function(n,e,o){r(n,e,o)&&t.push(n)});return t}function er(n,r,e){if(r=v.createCallback(r,e,3),!st(n)){var t;return wt(n,function(n,e,o){return r(n,e,o)?(t=n,!1):h}),t}for(var o=-1,u=n.length;++o<u;){var a=n[o];if(r(a,o,n))return a}}function tr(n,r,e){var t;return r=v.createCallback(r,e,3),ur(n,function(n,e,o){return r(n,e,o)?(t=n,!1):h}),t}function or(n,r,e){if(r&&"undefined"==typeof e&&st(n))for(var t=-1,o=n.length;++t<o&&r(n[t],t,n)!==!1;);else wt(n,r,e);return n}function ur(n,r,e){
var t=n,o=n?n.length:0;if(r=r&&"undefined"==typeof e?r:en(r,e,3),st(n))for(;o--&&r(n[o],o,n)!==!1;);else{if("number"!=typeof o){var u=gt(n);o=u.length}else lt.unindexedChars&&zn(n)&&(t=n.split(""));wt(n,function(n,e,a){return e=u?u[--o]:--o,r(t[e],e,a)})}return n}function ar(n,r){var e=p(arguments,2),t=-1,o="function"==typeof r,u=n?n.length:0,a=we("number"==typeof u?u:0);return or(n,function(n){a[++t]=(o?r:n[r]).apply(n,e)}),a}function ir(n,r,e){var t=-1,o=n?n.length:0,u=we("number"==typeof o?o:0);
if(r=v.createCallback(r,e,3),st(n))for(;++t<o;)u[t]=r(n[t],t,n);else wt(n,function(n,e,o){u[++t]=r(n,e,o)});return u}function lr(n,r,e){var o=-(1/0),u=o;if("function"!=typeof r&&e&&e[r]===n&&(r=null),null==r&&st(n))for(var a=-1,i=n.length;++a<i;){var l=n[a];l>u&&(u=l)}else r=null==r&&zn(n)?t:v.createCallback(r,e,3),wt(n,function(n,e,t){var a=r(n,e,t);a>o&&(o=a,u=n)});return u}function cr(n,r,e){var o=1/0,u=o;if("function"!=typeof r&&e&&e[r]===n&&(r=null),null==r&&st(n))for(var a=-1,i=n.length;++a<i;){
var l=n[a];l<u&&(u=l)}else r=null==r&&zn(n)?t:v.createCallback(r,e,3),wt(n,function(n,e,t){var a=r(n,e,t);a<o&&(o=a,u=n)});return u}function fr(n,r,e,t){var o=arguments.length<3;if(r=v.createCallback(r,t,4),st(n)){var u=-1,a=n.length;for(o&&(e=n[++u]);++u<a;)e=r(e,n[u],u,n)}else wt(n,function(n,t,u){e=o?(o=!1,n):r(e,n,t,u)});return e}function sr(n,r,e,t){var o=arguments.length<3;return r=v.createCallback(r,t,4),ur(n,function(n,t,u){e=o?(o=!1,n):r(e,n,t,u)}),e}function pr(n,r,e){return r=v.createCallback(r,e,3),
rr(n,function(n,e,t){return!r(n,e,t)})}function gr(n,r,e){if(n&&"number"!=typeof n.length?n=Xn(n):lt.unindexedChars&&zn(n)&&(n=n.split("")),null==r||e)return n?n[fn(0,n.length-1)]:h;var t=hr(n);return t.length=tt(et(0,r),t.length),t}function hr(n){var r=-1,e=n?n.length:0,t=we("number"==typeof e?e:0);return or(n,function(n){var e=fn(0,++r);t[r]=t[e],t[e]=n}),t}function vr(n){var r=n?n.length:0;return"number"==typeof r?r:gt(n).length}function yr(n,r,e){var t;if(r=v.createCallback(r,e,3),st(n))for(var o=-1,u=n.length;++o<u&&!(t=r(n[o],o,n)););else wt(n,function(n,e,o){
return!(t=r(n,e,o))});return!!t}function br(n,r,e){var t=-1,u=st(r),a=n?n.length:0,c=we("number"==typeof a?a:0);for(u||(r=v.createCallback(r,e,3)),or(n,function(n,e,o){var a=c[++t]=l();u?a.criteria=ir(r,function(r){return n[r]}):(a.criteria=i())[0]=r(n,e,o),a.index=t,a.value=n}),a=c.length,c.sort(o);a--;){var p=c[a];c[a]=p.value,u||f(p.criteria),s(p)}return c}function dr(n){return n&&"number"==typeof n.length?lt.unindexedChars&&zn(n)?n.split(""):p(n):Xn(n)}function mr(n){for(var r=-1,e=n?n.length:0,t=[];++r<e;){
var o=n[r];o&&t.push(o)}return t}function _r(n){return on(n,an(arguments,!0,!0,1))}function wr(n,r,e){var t=-1,o=n?n.length:0;for(r=v.createCallback(r,e,3);++t<o;)if(r(n[t],t,n))return t;return-1}function xr(n,r,e){var t=n?n.length:0;for(r=v.createCallback(r,e,3);t--;)if(r(n[t],t,n))return t;return-1}function jr(n,r,e){var t=0,o=n?n.length:0;if("number"!=typeof r&&null!=r){var u=-1;for(r=v.createCallback(r,e,3);++u<o&&r(n[u],u,n);)t++}else if(t=r,null==t||e)return n?n[0]:h;return p(n,0,tt(et(0,t),o));
}function kr(n,r,e,t){return"boolean"!=typeof r&&null!=r&&(t=e,e="function"!=typeof r&&t&&t[r]===n?null:r,r=!1),null!=e&&(n=ir(n,e,t)),an(n,r)}function Cr(r,e,t){if("number"==typeof t){var o=r?r.length:0;t=t<0?et(0,o+t):t||0}else if(t){var u=Rr(r,e);return r[u]===e?u:-1}return n(r,e,t)}function Pr(n,r,e){var t=0,o=n?n.length:0;if("number"!=typeof r&&null!=r){var u=o;for(r=v.createCallback(r,e,3);u--&&r(n[u],u,n);)t++}else t=null==r||e?1:r||t;return p(n,0,tt(et(0,o-t),o))}function Er(){for(var e=[],t=-1,o=arguments.length,a=i(),l=yn(),c=l===n,p=i();++t<o;){
var g=arguments[t];(st(g)||_n(g))&&(e.push(g),a.push(c&&g.length>=_&&u(t?e[t]:p)))}var h=e[0],v=-1,y=h?h.length:0,b=[];n:for(;++v<y;){var d=a[0];if(g=h[v],(d?r(d,g):l(p,g))<0){for(t=o,(d||p).push(g);--t;)if(d=a[t],(d?r(d,g):l(e[t],g))<0)continue n;b.push(g)}}for(;o--;)d=a[o],d&&s(d);return f(a),f(p),b}function Or(n,r,e){var t=0,o=n?n.length:0;if("number"!=typeof r&&null!=r){var u=o;for(r=v.createCallback(r,e,3);u--&&r(n[u],u,n);)t++}else if(t=r,null==t||e)return n?n[o-1]:h;return p(n,et(0,o-t))}function Sr(n,r,e){
var t=n?n.length:0;for("number"==typeof e&&(t=(e<0?et(0,t+e):tt(e,t-1))+1);t--;)if(n[t]===r)return t;return-1}function Ar(n){for(var r=arguments,e=0,t=r.length,o=n?n.length:0;++e<t;)for(var u=-1,a=r[e];++u<o;)n[u]===a&&(Ge.call(n,u--,1),o--);return n}function Ir(n,r,e){n=+n||0,e="number"==typeof e?e:+e||1,null==r&&(r=n,n=0);for(var t=-1,o=et(0,Be((r-n)/(e||1))),u=we(o);++t<o;)u[t]=n,n+=e;return u}function Lr(n,r,e){var t=-1,o=n?n.length:0,u=[];for(r=v.createCallback(r,e,3);++t<o;){var a=n[t];r(a,t,n)&&(u.push(a),
Ge.call(n,t--,1),o--)}return u}function Nr(n,r,e){if("number"!=typeof r&&null!=r){var t=0,o=-1,u=n?n.length:0;for(r=v.createCallback(r,e,3);++o<u&&r(n[o],o,n);)t++}else t=null==r||e?1:et(0,r);return p(n,t)}function Rr(n,r,e,t){var o=0,u=n?n.length:o;for(e=e?v.createCallback(e,t,1):ue,r=e(r);o<u;){var a=o+u>>>1;e(n[a])<r?o=a+1:u=a}return o}function Tr(){return sn(an(arguments,!0,!0))}function Dr(n,r,e,t){return"boolean"!=typeof r&&null!=r&&(t=e,e="function"!=typeof r&&t&&t[r]===n?null:r,r=!1),null!=e&&(e=v.createCallback(e,t,3)),
sn(n,r,e)}function $r(n){return on(n,p(arguments,1))}function Fr(){for(var n=-1,r=arguments.length;++n<r;){var e=arguments[n];if(st(e)||_n(e))var t=t?sn(on(t,e).concat(on(e,t))):e}return t||[]}function Br(){for(var n=arguments.length>1?arguments:arguments[0],r=-1,e=n?lr(At(n,"length")):0,t=we(e<0?0:e);++r<e;)t[r]=At(n,r);return t}function Hr(n,r){var e=-1,t=n?n.length:0,o={};for(r||!t||st(n[0])||(r=[]);++e<t;){var u=n[e];r?o[u]=r[e]:u&&(o[u[0]]=u[1])}return o}function Wr(n,r){if(!$n(r))throw new Ie;
return function(){return--n<1?r.apply(this,arguments):h}}function qr(n,r){return arguments.length>2?gn(n,17,p(arguments,2),null,r):gn(n,1,null,null,r)}function zr(n){for(var r=arguments.length>1?an(arguments,!0,!1,1):On(n),e=-1,t=r.length;++e<t;){var o=r[e];n[o]=gn(n[o],1,null,null,n)}return n}function Kr(n,r){return arguments.length>2?gn(r,19,p(arguments,2),null,n):gn(r,3,null,null,n)}function Ur(){for(var n=arguments,r=n.length;r--;)if(!$n(n[r]))throw new Ie;return function(){for(var r=arguments,e=n.length;e--;)r=[n[e].apply(this,r)];
return r[0]}}function Mr(n,r){return r="number"==typeof r?r:+r||n.length,gn(n,4,null,null,null,r)}function Vr(n,r,e){var t,o,u,a,i,l,c,f=0,s=!1,p=!0;if(!$n(n))throw new Ie;if(r=et(0,r)||0,e===!0){var g=!0;p=!1}else Fn(e)&&(g=e.leading,s="maxWait"in e&&(et(r,e.maxWait)||0),p="trailing"in e?e.trailing:p);var v=function(){var e=r-(Lt()-a);if(e>0)l=Ve(v,e);else{o&&He(o);var s=c;o=l=c=h,s&&(f=Lt(),u=n.apply(i,t),l||o||(t=i=null))}},y=function(){l&&He(l),o=l=c=h,(p||s!==r)&&(f=Lt(),u=n.apply(i,t),l||o||(t=i=null));
};return function(){if(t=arguments,a=Lt(),i=this,c=p&&(l||!g),s===!1)var e=g&&!l;else{o||g||(f=a);var h=s-(a-f),b=h<=0;b?(o&&(o=He(o)),f=a,u=n.apply(i,t)):o||(o=Ve(y,h))}return b&&l?l=He(l):l||r===s||(l=Ve(v,r)),e&&(b=!0,u=n.apply(i,t)),!b||l||o||(t=i=null),u}}function Gr(n){if(!$n(n))throw new Ie;var r=p(arguments,1);return Ve(function(){n.apply(h,r)},1)}function Jr(n,r){if(!$n(n))throw new Ie;var e=p(arguments,2);return Ve(function(){n.apply(h,e)},r)}function Qr(n,r){if(!$n(n))throw new Ie;var e=function(){
var t=e.cache,o=r?r.apply(this,arguments):m+arguments[0];return Ke.call(t,o)?t[o]:t[o]=n.apply(this,arguments)};return e.cache={},e}function Xr(n){var r,e;if(!$n(n))throw new Ie;return function(){return r?e:(r=!0,e=n.apply(this,arguments),n=null,e)}}function Yr(n){return gn(n,16,p(arguments,1))}function Zr(n){return gn(n,32,null,p(arguments,1))}function ne(n,r,e){var t=!0,o=!0;if(!$n(n))throw new Ie;return e===!1?t=!1:Fn(e)&&(t="leading"in e?e.leading:t,o="trailing"in e?e.trailing:o),J.leading=t,
J.maxWait=r,J.trailing=o,Vr(n,r,J)}function re(n,r){return gn(r,16,[n])}function ee(n){return function(){return n}}function te(n,r,e){var t=typeof n;if(null==n||"function"==t)return en(n,r,e);if("object"!=t)return ce(n);var o=gt(n),u=o[0],a=n[u];return 1!=o.length||a!==a||Fn(a)?function(r){for(var e=o.length,t=!1;e--&&(t=ln(r[o[e]],n[o[e]],null,!0)););return t}:function(n){var r=n[u];return a===r&&(0!==a||1/a==1/r)}}function oe(n){return null==n?"":Ae(n).replace(_t,vn)}function ue(n){return n}function ae(n,r,e){
var t=!0,o=r&&On(r);r&&(e||o.length)||(null==e&&(e=r),u=y,r=n,n=v,o=On(r)),e===!1?t=!1:Fn(e)&&"chain"in e&&(t=e.chain);var u=n,a=$n(u);or(o,function(e){var o=n[e]=r[e];a&&(u.prototype[e]=function(){var r=this.__chain__,e=this.__wrapped__,a=[e];Ue.apply(a,arguments);var i=o.apply(n,a);if(t||r){if(e===i&&Fn(i))return this;i=new u(i),i.__chain__=r}return i})})}function ie(){return e._=De,this}function le(){}function ce(n){return function(r){return r[n]}}function fe(n,r,e){var t=null==n,o=null==r;if(null==e&&("boolean"==typeof n&&o?(e=n,
n=1):o||"boolean"!=typeof r||(e=r,o=!0)),t&&o&&(r=1),n=+n||0,o?(r=n,n=0):r=+r||0,e||n%1||r%1){var u=ut();return tt(n+u*(r-n+parseFloat("1e-"+((u+"").length-1))),r)}return fn(n,r)}function se(n,r){if(n){var e=n[r];return $n(e)?n[r]():e}}function pe(n,r,e){var t=v.templateSettings;n=Ae(n||""),e=jt({},e,t);var o,u=jt({},e.imports,t.imports),i=gt(u),l=Xn(u),c=0,f=e.interpolate||L,s="__p += '",p=Se((e.escape||L).source+"|"+f.source+"|"+(f===A?E:L).source+"|"+(e.evaluate||L).source+"|$","g");n.replace(p,function(r,e,t,u,i,l){
return t||(t=u),s+=n.slice(c,l).replace(R,a),e&&(s+="' +\n__e("+e+") +\n'"),i&&(o=!0,s+="';\n"+i+";\n__p += '"),t&&(s+="' +\n((__t = ("+t+")) == null ? '' : __t) +\n'"),c=l+r.length,r}),s+="';\n";var g=e.variable,y=g;y||(g="obj",s="with ("+g+") {\n"+s+"\n}\n"),s=(o?s.replace(j,""):s).replace(C,"$1").replace(P,"$1;"),s="function("+g+") {\n"+(y?"":g+" || ("+g+" = {});\n")+"var __t, __p = '', __e = _.escape"+(o?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+s+"return __p\n}";
var b="\n/*\n//# sourceURL="+(e.sourceURL||"/lodash/template/source["+$++ +"]")+"\n*/";try{var d=Ce(i,"return "+s+b).apply(h,l)}catch(m){throw m.source=s,m}return r?d(r):(d.source=s,d)}function ge(n,r,e){n=(n=+n)>-1?n:0;var t=-1,o=we(n);for(r=en(r,e,1);++t<n;)o[t]=r(t);return o}function he(n){return null==n?"":Ae(n).replace(mt,mn)}function ve(n){var r=++b;return Ae(null==n?"":n)+r}function ye(n){return n=new y(n),n.__chain__=!0,n}function be(n,r){return r(n),n}function de(){return this.__chain__=!0,
this}function me(){return Ae(this.__wrapped__)}function _e(){return this.__wrapped__}e=e?un.defaults(nn.Object(),e,un.pick(nn,T)):nn;var we=e.Array,xe=e.Boolean,je=e.Date,ke=e.Error,Ce=e.Function,Pe=e.Math,Ee=e.Number,Oe=e.Object,Se=e.RegExp,Ae=e.String,Ie=e.TypeError,Le=[],Ne=ke.prototype,Re=Oe.prototype,Te=Ae.prototype,De=e._,$e=Re.toString,Fe=Se("^"+Ae($e).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),Be=Pe.ceil,He=e.clearTimeout,We=Pe.floor,qe=Ce.prototype.toString,ze=bn(ze=Oe.getPrototypeOf)&&ze,Ke=Re.hasOwnProperty,Ue=Le.push,Me=Re.propertyIsEnumerable,Ve=e.setTimeout,Ge=Le.splice,Je=Le.unshift,Qe=function(){
try{var n={},r=bn(r=Oe.defineProperty)&&r,e=r(n,n,n)&&r}catch(t){}return e}(),Xe=bn(Xe=Oe.create)&&Xe,Ye=bn(Ye=we.isArray)&&Ye,Ze=e.isFinite,nt=e.isNaN,rt=bn(rt=Oe.keys)&&rt,et=Pe.max,tt=Pe.min,ot=e.parseInt,ut=Pe.random,at={};at[B]=we,at[H]=xe,at[W]=je,at[z]=Ce,at[U]=Oe,at[K]=Ee,at[M]=Se,at[V]=Ae;var it={};it[B]=it[W]=it[K]={constructor:!0,toLocaleString:!0,toString:!0,valueOf:!0},it[H]=it[V]={constructor:!0,toString:!0,valueOf:!0},it[q]=it[z]=it[M]={constructor:!0,toString:!0},it[U]={constructor:!0
},function(){for(var n=D.length;n--;){var r=D[n];for(var e in it)Ke.call(it,e)&&!Ke.call(it[e],r)&&(it[e][r]=!1)}}(),y.prototype=v.prototype;var lt=v.support={};!function(){var n=function(){this.x=1},r={0:1,length:1},t=[];n.prototype={valueOf:1,y:1};for(var o in new n)t.push(o);for(o in arguments);lt.argsClass=$e.call(arguments)==F,lt.argsObject=arguments.constructor==Oe&&!(arguments instanceof we),lt.enumErrorProps=Me.call(Ne,"message")||Me.call(Ne,"name"),lt.enumPrototypes=Me.call(n,"prototype"),
lt.funcDecomp=!bn(e.WinRTError)&&N.test(g),lt.funcNames="string"==typeof Ce.name,lt.nonEnumArgs=0!=o,lt.nonEnumShadows=!/valueOf/.test(t),lt.ownLast="x"!=t[0],lt.spliceObjects=(Le.splice.call(r,0,1),!r[0]),lt.unindexedChars="x"[0]+Oe("x")[0]!="xx";try{lt.nodeClass=!($e.call(document)==U&&!({toString:0}+""))}catch(u){lt.nodeClass=!0}}(1),v.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:A,variable:"",imports:{_:v}};var ct=function(n){var r="var index, iterable = "+n.firstArg+", result = "+n.init+";\nif (!iterable) return result;\n"+n.top+";";
n.array?(r+="\nvar length = iterable.length; index = -1;\nif ("+n.array+") { ",lt.unindexedChars&&(r+="\n if (isString(iterable)) {\n iterable = iterable.split('')\n } "),r+="\n while (++index < length) {\n "+n.loop+";\n }\n}\nelse { "):lt.nonEnumArgs&&(r+="\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += '';\n "+n.loop+";\n }\n } else { "),lt.enumPrototypes&&(r+="\n var skipProto = typeof iterable == 'function';\n "),
lt.enumErrorProps&&(r+="\n var skipErrorProps = iterable === errorProto || iterable instanceof Error;\n ");var e=[];if(lt.enumPrototypes&&e.push('!(skipProto && index == "prototype")'),lt.enumErrorProps&&e.push('!(skipErrorProps && (index == "message" || index == "name"))'),n.useHas&&n.keys)r+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] && keys(iterable),\n length = ownProps ? ownProps.length : 0;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n",
e.length&&(r+=" if ("+e.join(" && ")+") {\n "),r+=n.loop+"; ",e.length&&(r+="\n }"),r+="\n } ";else if(r+="\n for (index in iterable) {\n",n.useHas&&e.push("hasOwnProperty.call(iterable, index)"),e.length&&(r+=" if ("+e.join(" && ")+") {\n "),r+=n.loop+"; ",e.length&&(r+="\n }"),r+="\n } ",lt.nonEnumShadows){for(r+="\n\n if (iterable !== objectProto) {\n var ctor = iterable.constructor,\n isProto = iterable === (ctor && ctor.prototype),\n className = iterable === stringProto ? stringClass : iterable === errorProto ? errorClass : toString.call(iterable),\n nonEnum = nonEnumProps[className];\n ",
k=0;k<7;k++)r+="\n index = '"+n.shadowedProps[k]+"';\n if ((!(isProto && nonEnum[index]) && hasOwnProperty.call(iterable, index))",n.useHas||(r+=" || (!nonEnum[index] && iterable[index] !== objectProto[index])"),r+=") {\n "+n.loop+";\n } ";r+="\n } "}return(n.array||lt.nonEnumArgs)&&(r+="\n}"),r+=n.bottom+";\nreturn result"};Xe||(rn=function(){function n(){}return function(r){if(Fn(r)){n.prototype=r;var t=new n;n.prototype=null}return t||e.Object()}}());var ft=Qe?function(n,r){
Q.value=r,Qe(n,"__bindData__",Q),Q.value=null}:le;lt.argsClass||(_n=function(n){return n&&"object"==typeof n&&"number"==typeof n.length&&Ke.call(n,"callee")&&!Me.call(n,"callee")||!1});var st=Ye||function(n){return n&&"object"==typeof n&&"number"==typeof n.length&&$e.call(n)==B||!1},pt=hn({args:"object",init:"[]",top:"if (!(objectTypes[typeof object])) return result",loop:"result.push(index)"}),gt=rt?function(n){return Fn(n)?lt.enumPrototypes&&"function"==typeof n||lt.nonEnumArgs&&n.length&&_n(n)?pt(n):rt(n):[];
}:pt,ht={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3)",array:"typeof length == 'number'",keys:gt,loop:"if (callback(iterable[index], index, collection) === false) return result"},vt={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",
keys:gt,loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},yt={top:"if (!objectTypes[typeof iterable]) return result;\n"+ht.top,array:!1},bt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},dt=An(bt),mt=Se("("+gt(dt).join("|")+")","g"),_t=Se("["+gt(bt).join("")+"]","g"),wt=hn(ht),xt=hn(vt,{top:vt.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),
loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),jt=hn(vt),kt=hn(ht,yt,{useHas:!1}),Ct=hn(ht,yt);$n(/x/)&&($n=function(n){return"function"==typeof n&&$e.call(n)==z});var Pt=ze?function(n){if(!n||$e.call(n)!=U||!lt.argsClass&&_n(n))return!1;var r=n.valueOf,e=bn(r)&&(e=ze(r))&&ze(e);return e?n==e||ze(n)==e:dn(n)}:dn,Et=pn(function(n,r,e){Ke.call(n,e)?n[e]++:n[e]=1}),Ot=pn(function(n,r,e){(Ke.call(n,e)?n[e]:n[e]=[]).push(r)}),St=pn(function(n,r,e){n[e]=r;
}),At=ir,It=rr,Lt=bn(Lt=je.now)&&Lt||function(){return(new je).getTime()},Nt=8==ot(x+"08")?ot:function(n,r){return ot(zn(n)?n.replace(I,""):n,r||0)};return v.after=Wr,v.assign=xt,v.at=Yn,v.bind=qr,v.bindAll=zr,v.bindKey=Kr,v.chain=ye,v.compact=mr,v.compose=Ur,v.constant=ee,v.countBy=Et,v.create=jn,v.createCallback=te,v.curry=Mr,v.debounce=Vr,v.defaults=jt,v.defer=Gr,v.delay=Jr,v.difference=_r,v.filter=rr,v.flatten=kr,v.forEach=or,v.forEachRight=ur,v.forIn=kt,v.forInRight=Pn,v.forOwn=Ct,v.forOwnRight=En,
v.functions=On,v.groupBy=Ot,v.indexBy=St,v.initial=Pr,v.intersection=Er,v.invert=An,v.invoke=ar,v.keys=gt,v.map=ir,v.mapValues=Un,v.max=lr,v.memoize=Qr,v.merge=Mn,v.min=cr,v.omit=Vn,v.once=Xr,v.pairs=Gn,v.partial=Yr,v.partialRight=Zr,v.pick=Jn,v.pluck=At,v.property=ce,v.pull=Ar,v.range=Ir,v.reject=pr,v.remove=Lr,v.rest=Nr,v.shuffle=hr,v.sortBy=br,v.tap=be,v.throttle=ne,v.times=ge,v.toArray=dr,v.transform=Qn,v.union=Tr,v.uniq=Dr,v.values=Xn,v.where=It,v.without=$r,v.wrap=re,v.xor=Fr,v.zip=Br,v.zipObject=Hr,
v.collect=ir,v.drop=Nr,v.each=or,v.eachRight=ur,v.extend=xt,v.methods=On,v.object=Hr,v.select=rr,v.tail=Nr,v.unique=Dr,v.unzip=Br,ae(v),v.clone=wn,v.cloneDeep=xn,v.contains=Zn,v.escape=oe,v.every=nr,v.find=er,v.findIndex=wr,v.findKey=kn,v.findLast=tr,v.findLastIndex=xr,v.findLastKey=Cn,v.has=Sn,v.identity=ue,v.indexOf=Cr,v.isArguments=_n,v.isArray=st,v.isBoolean=In,v.isDate=Ln,v.isElement=Nn,v.isEmpty=Rn,v.isEqual=Tn,v.isFinite=Dn,v.isFunction=$n,v.isNaN=Bn,v.isNull=Hn,v.isNumber=Wn,v.isObject=Fn,
v.isPlainObject=Pt,v.isRegExp=qn,v.isString=zn,v.isUndefined=Kn,v.lastIndexOf=Sr,v.mixin=ae,v.noConflict=ie,v.noop=le,v.now=Lt,v.parseInt=Nt,v.random=fe,v.reduce=fr,v.reduceRight=sr,v.result=se,v.runInContext=g,v.size=vr,v.some=yr,v.sortedIndex=Rr,v.template=pe,v.unescape=he,v.uniqueId=ve,v.all=nr,v.any=yr,v.detect=er,v.findWhere=er,v.foldl=fr,v.foldr=sr,v.include=Zn,v.inject=fr,ae(function(){var n={};return Ct(v,function(r,e){v.prototype[e]||(n[e]=r)}),n}(),!1),v.first=jr,v.last=Or,v.sample=gr,v.take=jr,
v.head=jr,Ct(v,function(n,r){var e="sample"!==r;v.prototype[r]||(v.prototype[r]=function(r,t){var o=this.__chain__,u=n(this.__wrapped__,r,t);return o||null!=r&&(!t||e&&"function"==typeof r)?new y(u,o):u})}),v.VERSION="2.4.2",v.prototype.chain=de,v.prototype.toString=me,v.prototype.value=_e,v.prototype.valueOf=_e,wt(["join","pop","shift"],function(n){var r=Le[n];v.prototype[n]=function(){var n=this.__chain__,e=r.apply(this.__wrapped__,arguments);return n?new y(e,n):e}}),wt(["push","reverse","sort","unshift"],function(n){
var r=Le[n];v.prototype[n]=function(){return r.apply(this.__wrapped__,arguments),this}}),wt(["concat","slice","splice"],function(n){var r=Le[n];v.prototype[n]=function(){return new y(r.apply(this.__wrapped__,arguments),this.__chain__)}}),lt.spliceObjects||wt(["pop","shift","splice"],function(n){var r=Le[n],e="splice"==n;v.prototype[n]=function(){var n=this.__chain__,t=this.__wrapped__,o=r.apply(t,arguments);return 0===t.length&&delete t[0],n||e?new y(o,n):o}}),v}var h,v=[],y=[],b=0,d={},m=+new Date+"",_=75,w=40,x=" \f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",j=/\b__p \+= '';/g,C=/\b(__p \+=) '' \+/g,P=/(__e\(.*?\)|\b__t\)) \+\n'';/g,E=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,O=/\w*$/,S=/^\s*function[ \n\r\t]+\w/,A=/<%=([\s\S]+?)%>/g,I=RegExp("^["+x+"]*0+(?=.$)"),L=/($^)/,N=/\bthis\b/,R=/['\n\r\t\u2028\u2029\\]/g,T=["Array","Boolean","Date","Error","Function","Math","Number","Object","RegExp","String","_","attachEvent","clearTimeout","isFinite","isNaN","parseInt","setTimeout"],D=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],$=0,F="[object Arguments]",B="[object Array]",H="[object Boolean]",W="[object Date]",q="[object Error]",z="[object Function]",K="[object Number]",U="[object Object]",M="[object RegExp]",V="[object String]",G={};
G[z]=!1,G[F]=G[B]=G[H]=G[W]=G[K]=G[U]=G[M]=G[V]=!0;var J={leading:!1,maxWait:0,trailing:!1},Q={configurable:!1,enumerable:!1,value:null,writable:!1},X={args:"",array:null,bottom:"",firstArg:"",init:"",keys:null,loop:"",shadowedProps:null,support:null,top:"",useHas:!1},Y={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},Z={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},nn=Y[typeof window]&&window||this,rn=Y[typeof exports]&&exports&&!exports.nodeType&&exports,en=Y[typeof module]&&module&&!module.nodeType&&module,tn=en&&en.exports===rn&&rn,on=Y[typeof global]&&global;
!on||on.global!==on&&on.window!==on||(nn=on);var un=g();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(nn._=un,define(function(){return un})):rn&&en?tn?(en.exports=un)._=un:rn._=un:nn._=un}).call(this);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* @license
* Lo-Dash 2.4.2 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Build: `lodash modern -o ./dist/lodash.js`
*/
;(function(){function n(n,r,t){for(var e=(t||0)-1,u=n?n.length:0;++e<u;)if(n[e]===r)return e;return-1}function r(r,t){var e=typeof t;if(r=r.cache,"boolean"==e||null==t)return r[t]?0:-1;"number"!=e&&"string"!=e&&(e="object");var u="number"==e?t:m+t;return r=(r=r[e])&&r[u],"object"==e?r&&n(r,t)>-1?0:-1:r?0:-1}function t(n){var r=this.cache,t=typeof n;if("boolean"==t||null==n)r[n]=!0;else{"number"!=t&&"string"!=t&&(t="object");var e="number"==t?n:m+n,u=r[t]||(r[t]={});"object"==t?(u[e]||(u[e]=[])).push(n):u[e]=!0;
}}function e(n){return n.charCodeAt(0)}function u(n,r){for(var t=n.criteria,e=r.criteria,u=-1,o=t.length;++u<o;){var a=t[u],i=e[u];if(a!==i){if(a>i||"undefined"==typeof a)return 1;if(a<i||"undefined"==typeof i)return-1}}return n.index-r.index}function o(n){var r=-1,e=n.length,u=n[0],o=n[e/2|0],a=n[e-1];if(u&&"object"==typeof u&&o&&"object"==typeof o&&a&&"object"==typeof a)return!1;var i=f();i["false"]=i["null"]=i["true"]=i.undefined=!1;var l=f();for(l.array=n,l.cache=i,l.push=t;++r<e;)l.push(n[r]);
return l}function a(n){return"\\"+G[n]}function i(){return h.pop()||[]}function f(){return g.pop()||{array:null,cache:null,criteria:null,"false":!1,index:0,"null":!1,number:null,object:null,push:null,string:null,"true":!1,undefined:!1,value:null}}function l(n){n.length=0,h.length<_&&h.push(n)}function c(n){var r=n.cache;r&&c(r),n.array=n.cache=n.criteria=n.object=n.number=n.string=n.value=null,g.length<_&&g.push(n)}function p(n,r,t){r||(r=0),"undefined"==typeof t&&(t=n?n.length:0);for(var e=-1,u=t-r||0,o=Array(u<0?0:u);++e<u;)o[e]=n[r+e];
return o}function s(t){function h(n){return n&&"object"==typeof n&&!Yt(n)&&Tt.call(n,"__wrapped__")?n:new g(n)}function g(n,r){this.__chain__=!!r,this.__wrapped__=n}function _(n){function r(){if(e){var n=p(e);$t.apply(n,arguments)}if(this instanceof r){var o=J(t.prototype),a=t.apply(o,n||arguments);return Sn(a)?a:o}return t.apply(u,n||arguments)}var t=n[0],e=n[2],u=n[4];return Xt(r,n),r}function G(n,r,t,e,u){if(t){var o=t(n);if("undefined"!=typeof o)return o}var a=Sn(n);if(!a)return n;var f=Nt.call(n);
if(!K[f])return n;var c=Jt[f];switch(f){case F:case B:return new c(+n);case q:case P:return new c(n);case L:return o=c(n.source,C.exec(n)),o.lastIndex=n.lastIndex,o}var s=Yt(n);if(r){var v=!e;e||(e=i()),u||(u=i());for(var h=e.length;h--;)if(e[h]==n)return u[h];o=s?c(n.length):{}}else o=s?p(n):oe({},n);return s&&(Tt.call(n,"index")&&(o.index=n.index),Tt.call(n,"input")&&(o.input=n.input)),r?(e.push(n),u.push(o),(s?Xn:fe)(n,function(n,a){o[a]=G(n,r,t,e,u)}),v&&(l(e),l(u)),o):o}function J(n,r){return Sn(n)?zt(n):{};
}function Q(n,r,t){if("function"!=typeof n)return Yr;if("undefined"==typeof r||!("prototype"in n))return n;var e=n.__bindData__;if("undefined"==typeof e&&(Qt.funcNames&&(e=!n.name),e=e||!Qt.funcDecomp,!e)){var u=At.call(n);Qt.funcNames||(e=!O.test(u)),e||(e=I.test(u),Xt(n,e))}if(e===!1||e!==!0&&1&e[1])return n;switch(t){case 1:return function(t){return n.call(r,t)};case 2:return function(t,e){return n.call(r,t,e)};case 3:return function(t,e,u){return n.call(r,t,e,u)};case 4:return function(t,e,u,o){
return n.call(r,t,e,u,o)}}return $r(n,r)}function X(n){function r(){var n=f?a:this;if(u){var h=p(u);$t.apply(h,arguments)}if((o||c)&&(h||(h=p(arguments)),o&&$t.apply(h,o),c&&h.length<i))return e|=16,X([t,s?e:-4&e,h,null,a,i]);if(h||(h=arguments),l&&(t=n[v]),this instanceof r){n=J(t.prototype);var g=t.apply(n,h);return Sn(g)?g:n}return t.apply(n,h)}var t=n[0],e=n[1],u=n[2],o=n[3],a=n[4],i=n[5],f=1&e,l=2&e,c=4&e,s=8&e,v=t;return Xt(r,n),r}function Y(t,e){var u=-1,a=ln(),i=t?t.length:0,f=i>=b&&a===n,l=[];
if(f){var p=o(e);p?(a=r,e=p):f=!1}for(;++u<i;){var s=t[u];a(e,s)<0&&l.push(s)}return f&&c(e),l}function nn(n,r,t,e){for(var u=(e||0)-1,o=n?n.length:0,a=[];++u<o;){var i=n[u];if(i&&"object"==typeof i&&"number"==typeof i.length&&(Yt(i)||vn(i))){r||(i=nn(i,r,t));var f=-1,l=i.length,c=a.length;for(a.length+=l;++f<l;)a[c++]=i[f]}else t||a.push(i)}return a}function rn(n,r,t,e,u,o){if(t){var a=t(n,r);if("undefined"!=typeof a)return!!a}if(n===r)return 0!==n||1/n==1/r;var f=typeof n,c=typeof r;if(n===n&&(!n||!V[f])&&(!r||!V[c]))return!1;
if(null==n||null==r)return n===r;var p=Nt.call(n),s=Nt.call(r);if(p==T&&(p=z),s==T&&(s=z),p!=s)return!1;switch(p){case F:case B:return+n==+r;case q:return n!=+n?r!=+r:0==n?1/n==1/r:n==+r;case L:case P:return n==jt(r)}var h=p==$;if(!h){var g=Tt.call(n,"__wrapped__"),y=Tt.call(r,"__wrapped__");if(g||y)return rn(g?n.__wrapped__:n,y?r.__wrapped__:r,t,e,u,o);if(p!=z)return!1;var m=n.constructor,b=r.constructor;if(m!=b&&!(In(m)&&m instanceof m&&In(b)&&b instanceof b)&&"constructor"in n&&"constructor"in r)return!1;
}var _=!u;u||(u=i()),o||(o=i());for(var d=u.length;d--;)if(u[d]==n)return o[d]==r;var w=0;if(a=!0,u.push(n),o.push(r),h){if(d=n.length,w=r.length,a=w==d,a||e)for(;w--;){var j=d,k=r[w];if(e)for(;j--&&!(a=rn(n[j],k,t,e,u,o)););else if(!(a=rn(n[w],k,t,e,u,o)))break}}else ie(r,function(r,i,f){return Tt.call(f,i)?(w++,a=Tt.call(n,i)&&rn(n[i],r,t,e,u,o)):v}),a&&!e&&ie(n,function(n,r,t){return Tt.call(t,r)?a=--w>-1:v});return u.pop(),o.pop(),_&&(l(u),l(o)),a}function tn(n,r,t,e,u){(Yt(r)?Xn:fe)(r,function(r,o){
var a,i,f=r,l=n[o];if(r&&((i=Yt(r))||le(r))){for(var c=e.length;c--;)if(a=e[c]==r){l=u[c];break}if(!a){var p;t&&(f=t(l,r),(p="undefined"!=typeof f)&&(l=f)),p||(l=i?Yt(l)?l:[]:le(l)?l:{}),e.push(r),u.push(l),p||tn(l,r,t,e,u)}}else t&&(f=t(l,r),"undefined"==typeof f&&(f=r)),"undefined"!=typeof f&&(l=f);n[o]=l})}function en(n,r){return n+St(Ht()*(r-n+1))}function un(t,e,u){var a=-1,f=ln(),p=t?t.length:0,s=[],v=!e&&p>=b&&f===n,h=u||v?i():s;if(v){var g=o(h);f=r,h=g}for(;++a<p;){var y=t[a],m=u?u(y,a,t):y;
(e?!a||h[h.length-1]!==m:f(h,m)<0)&&((u||v)&&h.push(m),s.push(y))}return v?(l(h.array),c(h)):u&&l(h),s}function on(n){return function(r,t,e){var u={};t=h.createCallback(t,e,3);var o=-1,a=r?r.length:0;if("number"==typeof a)for(;++o<a;){var i=r[o];n(u,i,t(i,o,r),r)}else fe(r,function(r,e,o){n(u,r,t(r,e,o),o)});return u}}function an(n,r,t,e,u,o){var a=1&r,i=2&r,f=4&r,l=16&r,c=32&r;if(!i&&!In(n))throw new kt;l&&!t.length&&(r&=-17,l=t=!1),c&&!e.length&&(r&=-33,c=e=!1);var s=n&&n.__bindData__;if(s&&s!==!0)return s=p(s),
s[2]&&(s[2]=p(s[2])),s[3]&&(s[3]=p(s[3])),!a||1&s[1]||(s[4]=u),!a&&1&s[1]&&(r|=8),!f||4&s[1]||(s[5]=o),l&&$t.apply(s[2]||(s[2]=[]),t),c&&Wt.apply(s[3]||(s[3]=[]),e),s[1]|=r,an.apply(null,s);var v=1==r||17===r?_:X;return v([n,r,t,e,u,o])}function fn(n){return re[n]}function ln(){var r=(r=h.indexOf)===br?n:r;return r}function cn(n){return"function"==typeof n&&Rt.test(n)}function pn(n){var r,t;return n&&Nt.call(n)==z&&(r=n.constructor,!In(r)||r instanceof r)?(ie(n,function(n,r){t=r}),"undefined"==typeof t||Tt.call(n,t)):!1;
}function sn(n){return te[n]}function vn(n){return n&&"object"==typeof n&&"number"==typeof n.length&&Nt.call(n)==T||!1}function hn(n,r,t,e){return"boolean"!=typeof r&&null!=r&&(e=t,t=r,r=!1),G(n,r,"function"==typeof t&&Q(t,e,1))}function gn(n,r,t){return G(n,!0,"function"==typeof r&&Q(r,t,1))}function yn(n,r){var t=J(n);return r?oe(t,r):t}function mn(n,r,t){var e;return r=h.createCallback(r,t,3),fe(n,function(n,t,u){return r(n,t,u)?(e=t,!1):v}),e}function bn(n,r,t){var e;return r=h.createCallback(r,t,3),
dn(n,function(n,t,u){return r(n,t,u)?(e=t,!1):v}),e}function _n(n,r,t){var e=[];ie(n,function(n,r){e.push(r,n)});var u=e.length;for(r=Q(r,t,3);u--&&r(e[u--],e[u],n)!==!1;);return n}function dn(n,r,t){var e=ne(n),u=e.length;for(r=Q(r,t,3);u--;){var o=e[u];if(r(n[o],o,n)===!1)break}return n}function wn(n){var r=[];return ie(n,function(n,t){In(n)&&r.push(t)}),r.sort()}function jn(n,r){return n?Tt.call(n,r):!1}function kn(n){for(var r=-1,t=ne(n),e=t.length,u={};++r<e;){var o=t[r];u[n[o]]=o}return u}function xn(n){
return n===!0||n===!1||n&&"object"==typeof n&&Nt.call(n)==F||!1}function Cn(n){return n&&"object"==typeof n&&Nt.call(n)==B||!1}function On(n){return n&&1===n.nodeType||!1}function Nn(n){var r=!0;if(!n)return r;var t=Nt.call(n),e=n.length;return t==$||t==P||t==T||t==z&&"number"==typeof e&&In(n.splice)?!e:(fe(n,function(){return r=!1}),r)}function Rn(n,r,t,e){return rn(n,r,"function"==typeof t&&Q(t,e,2))}function En(n){return Pt(n)&&!Kt(parseFloat(n))}function In(n){return"function"==typeof n}function Sn(n){
return!(!n||!V[typeof n])}function An(n){return Tn(n)&&n!=+n}function Dn(n){return null===n}function Tn(n){return"number"==typeof n||n&&"object"==typeof n&&Nt.call(n)==q||!1}function $n(n){return n&&"object"==typeof n&&Nt.call(n)==L||!1}function Fn(n){return"string"==typeof n||n&&"object"==typeof n&&Nt.call(n)==P||!1}function Bn(n){return"undefined"==typeof n}function Wn(n,r,t){var e={};return r=h.createCallback(r,t,3),fe(n,function(n,t,u){e[t]=r(n,t,u)}),e}function qn(n){var r=arguments,t=2;if(!Sn(n))return n;
if("number"!=typeof r[2]&&(t=r.length),t>3&&"function"==typeof r[t-2])var e=Q(r[--t-1],r[t--],2);else t>2&&"function"==typeof r[t-1]&&(e=r[--t]);for(var u=p(arguments,1,t),o=-1,a=i(),f=i();++o<t;)tn(n,u[o],e,a,f);return l(a),l(f),n}function zn(n,r,t){var e={};if("function"!=typeof r){var u=[];ie(n,function(n,r){u.push(r)}),u=Y(u,nn(arguments,!0,!1,1));for(var o=-1,a=u.length;++o<a;){var i=u[o];e[i]=n[i]}}else r=h.createCallback(r,t,3),ie(n,function(n,t,u){r(n,t,u)||(e[t]=n)});return e}function Ln(n){
for(var r=-1,t=ne(n),e=t.length,u=ht(e);++r<e;){var o=t[r];u[r]=[o,n[o]]}return u}function Pn(n,r,t){var e={};if("function"!=typeof r)for(var u=-1,o=nn(arguments,!0,!1,1),a=Sn(n)?o.length:0;++u<a;){var i=o[u];i in n&&(e[i]=n[i])}else r=h.createCallback(r,t,3),ie(n,function(n,t,u){r(n,t,u)&&(e[t]=n)});return e}function Kn(n,r,t,e){var u=Yt(n);if(null==t)if(u)t=[];else{var o=n&&n.constructor,a=o&&o.prototype;t=J(a)}return r&&(r=h.createCallback(r,e,4),(u?Xn:fe)(n,function(n,e,u){return r(t,n,e,u)})),
t}function Un(n){for(var r=-1,t=ne(n),e=t.length,u=ht(e);++r<e;)u[r]=n[t[r]];return u}function Mn(n){for(var r=arguments,t=-1,e=nn(r,!0,!1,1),u=r[2]&&r[2][r[1]]===n?1:e.length,o=ht(u);++t<u;)o[t]=n[e[t]];return o}function Vn(n,r,t){var e=-1,u=ln(),o=n?n.length:0,a=!1;return t=(t<0?Mt(0,o+t):t)||0,Yt(n)?a=u(n,r,t)>-1:"number"==typeof o?a=(Fn(n)?n.indexOf(r,t):u(n,r,t))>-1:fe(n,function(n){return++e<t?v:!(a=n===r)}),a}function Gn(n,r,t){var e=!0;r=h.createCallback(r,t,3);var u=-1,o=n?n.length:0;if("number"==typeof o)for(;++u<o&&(e=!!r(n[u],u,n)););else fe(n,function(n,t,u){
return e=!!r(n,t,u)});return e}function Hn(n,r,t){var e=[];r=h.createCallback(r,t,3);var u=-1,o=n?n.length:0;if("number"==typeof o)for(;++u<o;){var a=n[u];r(a,u,n)&&e.push(a)}else fe(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function Jn(n,r,t){r=h.createCallback(r,t,3);var e=-1,u=n?n.length:0;if("number"!=typeof u){var o;return fe(n,function(n,t,e){return r(n,t,e)?(o=n,!1):v}),o}for(;++e<u;){var a=n[e];if(r(a,e,n))return a}}function Qn(n,r,t){var e;return r=h.createCallback(r,t,3),Yn(n,function(n,t,u){
return r(n,t,u)?(e=n,!1):v}),e}function Xn(n,r,t){var e=-1,u=n?n.length:0;if(r=r&&"undefined"==typeof t?r:Q(r,t,3),"number"==typeof u)for(;++e<u&&r(n[e],e,n)!==!1;);else fe(n,r);return n}function Yn(n,r,t){var e=n?n.length:0;if(r=r&&"undefined"==typeof t?r:Q(r,t,3),"number"==typeof e)for(;e--&&r(n[e],e,n)!==!1;);else{var u=ne(n);e=u.length,fe(n,function(n,t,o){return t=u?u[--e]:--e,r(o[t],t,o)})}return n}function Zn(n,r){var t=p(arguments,2),e=-1,u="function"==typeof r,o=n?n.length:0,a=ht("number"==typeof o?o:0);
return Xn(n,function(n){a[++e]=(u?r:n[r]).apply(n,t)}),a}function nr(n,r,t){var e=-1,u=n?n.length:0;if(r=h.createCallback(r,t,3),"number"==typeof u)for(var o=ht(u);++e<u;)o[e]=r(n[e],e,n);else o=[],fe(n,function(n,t,u){o[++e]=r(n,t,u)});return o}function rr(n,r,t){var u=-(1/0),o=u;if("function"!=typeof r&&t&&t[r]===n&&(r=null),null==r&&Yt(n))for(var a=-1,i=n.length;++a<i;){var f=n[a];f>o&&(o=f)}else r=null==r&&Fn(n)?e:h.createCallback(r,t,3),Xn(n,function(n,t,e){var a=r(n,t,e);a>u&&(u=a,o=n)});return o;
}function tr(n,r,t){var u=1/0,o=u;if("function"!=typeof r&&t&&t[r]===n&&(r=null),null==r&&Yt(n))for(var a=-1,i=n.length;++a<i;){var f=n[a];f<o&&(o=f)}else r=null==r&&Fn(n)?e:h.createCallback(r,t,3),Xn(n,function(n,t,e){var a=r(n,t,e);a<u&&(u=a,o=n)});return o}function er(n,r,t,e){if(!n)return t;var u=arguments.length<3;r=h.createCallback(r,e,4);var o=-1,a=n.length;if("number"==typeof a)for(u&&(t=n[++o]);++o<a;)t=r(t,n[o],o,n);else fe(n,function(n,e,o){t=u?(u=!1,n):r(t,n,e,o)});return t}function ur(n,r,t,e){
var u=arguments.length<3;return r=h.createCallback(r,e,4),Yn(n,function(n,e,o){t=u?(u=!1,n):r(t,n,e,o)}),t}function or(n,r,t){return r=h.createCallback(r,t,3),Hn(n,function(n,t,e){return!r(n,t,e)})}function ar(n,r,t){if(n&&"number"!=typeof n.length&&(n=Un(n)),null==r||t)return n?n[en(0,n.length-1)]:v;var e=ir(n);return e.length=Vt(Mt(0,r),e.length),e}function ir(n){var r=-1,t=n?n.length:0,e=ht("number"==typeof t?t:0);return Xn(n,function(n){var t=en(0,++r);e[r]=e[t],e[t]=n}),e}function fr(n){var r=n?n.length:0;
return"number"==typeof r?r:ne(n).length}function lr(n,r,t){var e;r=h.createCallback(r,t,3);var u=-1,o=n?n.length:0;if("number"==typeof o)for(;++u<o&&!(e=r(n[u],u,n)););else fe(n,function(n,t,u){return!(e=r(n,t,u))});return!!e}function cr(n,r,t){var e=-1,o=Yt(r),a=n?n.length:0,p=ht("number"==typeof a?a:0);for(o||(r=h.createCallback(r,t,3)),Xn(n,function(n,t,u){var a=p[++e]=f();o?a.criteria=nr(r,function(r){return n[r]}):(a.criteria=i())[0]=r(n,t,u),a.index=e,a.value=n}),a=p.length,p.sort(u);a--;){
var s=p[a];p[a]=s.value,o||l(s.criteria),c(s)}return p}function pr(n){return n&&"number"==typeof n.length?p(n):Un(n)}function sr(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e}function vr(n){return Y(n,nn(arguments,!0,!0,1))}function hr(n,r,t){var e=-1,u=n?n.length:0;for(r=h.createCallback(r,t,3);++e<u;)if(r(n[e],e,n))return e;return-1}function gr(n,r,t){var e=n?n.length:0;for(r=h.createCallback(r,t,3);e--;)if(r(n[e],e,n))return e;return-1}function yr(n,r,t){var e=0,u=n?n.length:0;
if("number"!=typeof r&&null!=r){var o=-1;for(r=h.createCallback(r,t,3);++o<u&&r(n[o],o,n);)e++}else if(e=r,null==e||t)return n?n[0]:v;return p(n,0,Vt(Mt(0,e),u))}function mr(n,r,t,e){return"boolean"!=typeof r&&null!=r&&(e=t,t="function"!=typeof r&&e&&e[r]===n?null:r,r=!1),null!=t&&(n=nr(n,t,e)),nn(n,r)}function br(r,t,e){if("number"==typeof e){var u=r?r.length:0;e=e<0?Mt(0,u+e):e||0}else if(e){var o=Nr(r,t);return r[o]===t?o:-1}return n(r,t,e)}function _r(n,r,t){var e=0,u=n?n.length:0;if("number"!=typeof r&&null!=r){
var o=u;for(r=h.createCallback(r,t,3);o--&&r(n[o],o,n);)e++}else e=null==r||t?1:r||e;return p(n,0,Vt(Mt(0,u-e),u))}function dr(){for(var t=[],e=-1,u=arguments.length,a=i(),f=ln(),p=f===n,s=i();++e<u;){var v=arguments[e];(Yt(v)||vn(v))&&(t.push(v),a.push(p&&v.length>=b&&o(e?t[e]:s)))}var h=t[0],g=-1,y=h?h.length:0,m=[];n:for(;++g<y;){var _=a[0];if(v=h[g],(_?r(_,v):f(s,v))<0){for(e=u,(_||s).push(v);--e;)if(_=a[e],(_?r(_,v):f(t[e],v))<0)continue n;m.push(v)}}for(;u--;)_=a[u],_&&c(_);return l(a),l(s),
m}function wr(n,r,t){var e=0,u=n?n.length:0;if("number"!=typeof r&&null!=r){var o=u;for(r=h.createCallback(r,t,3);o--&&r(n[o],o,n);)e++}else if(e=r,null==e||t)return n?n[u-1]:v;return p(n,Mt(0,u-e))}function jr(n,r,t){var e=n?n.length:0;for("number"==typeof t&&(e=(t<0?Mt(0,e+t):Vt(t,e-1))+1);e--;)if(n[e]===r)return e;return-1}function kr(n){for(var r=arguments,t=0,e=r.length,u=n?n.length:0;++t<e;)for(var o=-1,a=r[t];++o<u;)n[o]===a&&(Bt.call(n,o--,1),u--);return n}function xr(n,r,t){n=+n||0,t="number"==typeof t?t:+t||1,
null==r&&(r=n,n=0);for(var e=-1,u=Mt(0,Et((r-n)/(t||1))),o=ht(u);++e<u;)o[e]=n,n+=t;return o}function Cr(n,r,t){var e=-1,u=n?n.length:0,o=[];for(r=h.createCallback(r,t,3);++e<u;){var a=n[e];r(a,e,n)&&(o.push(a),Bt.call(n,e--,1),u--)}return o}function Or(n,r,t){if("number"!=typeof r&&null!=r){var e=0,u=-1,o=n?n.length:0;for(r=h.createCallback(r,t,3);++u<o&&r(n[u],u,n);)e++}else e=null==r||t?1:Mt(0,r);return p(n,e)}function Nr(n,r,t,e){var u=0,o=n?n.length:u;for(t=t?h.createCallback(t,e,1):Yr,r=t(r);u<o;){
var a=u+o>>>1;t(n[a])<r?u=a+1:o=a}return u}function Rr(){return un(nn(arguments,!0,!0))}function Er(n,r,t,e){return"boolean"!=typeof r&&null!=r&&(e=t,t="function"!=typeof r&&e&&e[r]===n?null:r,r=!1),null!=t&&(t=h.createCallback(t,e,3)),un(n,r,t)}function Ir(n){return Y(n,p(arguments,1))}function Sr(){for(var n=-1,r=arguments.length;++n<r;){var t=arguments[n];if(Yt(t)||vn(t))var e=e?un(Y(e,t).concat(Y(t,e))):t}return e||[]}function Ar(){for(var n=arguments.length>1?arguments:arguments[0],r=-1,t=n?rr(ve(n,"length")):0,e=ht(t<0?0:t);++r<t;)e[r]=ve(n,r);
return e}function Dr(n,r){var t=-1,e=n?n.length:0,u={};for(r||!e||Yt(n[0])||(r=[]);++t<e;){var o=n[t];r?u[o]=r[t]:o&&(u[o[0]]=o[1])}return u}function Tr(n,r){if(!In(r))throw new kt;return function(){return--n<1?r.apply(this,arguments):v}}function $r(n,r){return arguments.length>2?an(n,17,p(arguments,2),null,r):an(n,1,null,null,r)}function Fr(n){for(var r=arguments.length>1?nn(arguments,!0,!1,1):wn(n),t=-1,e=r.length;++t<e;){var u=r[t];n[u]=an(n[u],1,null,null,n)}return n}function Br(n,r){return arguments.length>2?an(r,19,p(arguments,2),null,n):an(r,3,null,null,n);
}function Wr(){for(var n=arguments,r=n.length;r--;)if(!In(n[r]))throw new kt;return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}}function qr(n,r){return r="number"==typeof r?r:+r||n.length,an(n,4,null,null,null,r)}function zr(n,r,t){var e,u,o,a,i,f,l,c=0,p=!1,s=!0;if(!In(n))throw new kt;if(r=Mt(0,r)||0,t===!0){var h=!0;s=!1}else Sn(t)&&(h=t.leading,p="maxWait"in t&&(Mt(r,t.maxWait)||0),s="trailing"in t?t.trailing:s);var g=function(){var t=r-(ge()-a);if(t>0)f=Ft(g,t);
else{u&&It(u);var p=l;u=f=l=v,p&&(c=ge(),o=n.apply(i,e),f||u||(e=i=null))}},y=function(){f&&It(f),u=f=l=v,(s||p!==r)&&(c=ge(),o=n.apply(i,e),f||u||(e=i=null))};return function(){if(e=arguments,a=ge(),i=this,l=s&&(f||!h),p===!1)var t=h&&!f;else{u||h||(c=a);var v=p-(a-c),m=v<=0;m?(u&&(u=It(u)),c=a,o=n.apply(i,e)):u||(u=Ft(y,v))}return m&&f?f=It(f):f||r===p||(f=Ft(g,r)),t&&(m=!0,o=n.apply(i,e)),!m||f||u||(e=i=null),o}}function Lr(n){if(!In(n))throw new kt;var r=p(arguments,1);return Ft(function(){n.apply(v,r);
},1)}function Pr(n,r){if(!In(n))throw new kt;var t=p(arguments,2);return Ft(function(){n.apply(v,t)},r)}function Kr(n,r){if(!In(n))throw new kt;var t=function(){var e=t.cache,u=r?r.apply(this,arguments):m+arguments[0];return Tt.call(e,u)?e[u]:e[u]=n.apply(this,arguments)};return t.cache={},t}function Ur(n){var r,t;if(!In(n))throw new kt;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}}function Mr(n){return an(n,16,p(arguments,1))}function Vr(n){return an(n,32,null,p(arguments,1));
}function Gr(n,r,t){var e=!0,u=!0;if(!In(n))throw new kt;return t===!1?e=!1:Sn(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),U.leading=e,U.maxWait=r,U.trailing=u,zr(n,r,U)}function Hr(n,r){return an(r,16,[n])}function Jr(n){return function(){return n}}function Qr(n,r,t){var e=typeof n;if(null==n||"function"==e)return Q(n,r,t);if("object"!=e)return tt(n);var u=ne(n),o=u[0],a=n[o];return 1!=u.length||a!==a||Sn(a)?function(r){for(var t=u.length,e=!1;t--&&(e=rn(r[u[t]],n[u[t]],null,!0)););
return e}:function(n){var r=n[o];return a===r&&(0!==a||1/a==1/r)}}function Xr(n){return null==n?"":jt(n).replace(ue,fn)}function Yr(n){return n}function Zr(n,r,t){var e=!0,u=r&&wn(r);r&&(t||u.length)||(null==t&&(t=r),o=g,r=n,n=h,u=wn(r)),t===!1?e=!1:Sn(t)&&"chain"in t&&(e=t.chain);var o=n,a=In(o);Xn(u,function(t){var u=n[t]=r[t];a&&(o.prototype[t]=function(){var r=this.__chain__,t=this.__wrapped__,a=[t];$t.apply(a,arguments);var i=u.apply(n,a);if(e||r){if(t===i&&Sn(i))return this;i=new o(i),i.__chain__=r;
}return i})})}function nt(){return t._=Ot,this}function rt(){}function tt(n){return function(r){return r[n]}}function et(n,r,t){var e=null==n,u=null==r;if(null==t&&("boolean"==typeof n&&u?(t=n,n=1):u||"boolean"!=typeof r||(t=r,u=!0)),e&&u&&(r=1),n=+n||0,u?(r=n,n=0):r=+r||0,t||n%1||r%1){var o=Ht();return Vt(n+o*(r-n+parseFloat("1e-"+((o+"").length-1))),r)}return en(n,r)}function ut(n,r){if(n){var t=n[r];return In(t)?n[r]():t}}function ot(n,r,t){var e=h.templateSettings;n=jt(n||""),t=ae({},t,e);var u,o=ae({},t.imports,e.imports),i=ne(o),f=Un(o),l=0,c=t.interpolate||E,p="__p += '",s=wt((t.escape||E).source+"|"+c.source+"|"+(c===N?x:E).source+"|"+(t.evaluate||E).source+"|$","g");
n.replace(s,function(r,t,e,o,i,f){return e||(e=o),p+=n.slice(l,f).replace(S,a),t&&(p+="' +\n__e("+t+") +\n'"),i&&(u=!0,p+="';\n"+i+";\n__p += '"),e&&(p+="' +\n((__t = ("+e+")) == null ? '' : __t) +\n'"),l=f+r.length,r}),p+="';\n";var g=t.variable,y=g;y||(g="obj",p="with ("+g+") {\n"+p+"\n}\n"),p=(u?p.replace(w,""):p).replace(j,"$1").replace(k,"$1;"),p="function("+g+") {\n"+(y?"":g+" || ("+g+" = {});\n")+"var __t, __p = '', __e = _.escape"+(u?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";
var m="\n/*\n//# sourceURL="+(t.sourceURL||"/lodash/template/source["+D++ +"]")+"\n*/";try{var b=mt(i,"return "+p+m).apply(v,f)}catch(_){throw _.source=p,_}return r?b(r):(b.source=p,b)}function at(n,r,t){n=(n=+n)>-1?n:0;var e=-1,u=ht(n);for(r=Q(r,t,1);++e<n;)u[e]=r(e);return u}function it(n){return null==n?"":jt(n).replace(ee,sn)}function ft(n){var r=++y;return jt(null==n?"":n)+r}function lt(n){return n=new g(n),n.__chain__=!0,n}function ct(n,r){return r(n),n}function pt(){return this.__chain__=!0,
this}function st(){return jt(this.__wrapped__)}function vt(){return this.__wrapped__}t=t?Z.defaults(H.Object(),t,Z.pick(H,A)):H;var ht=t.Array,gt=t.Boolean,yt=t.Date,mt=t.Function,bt=t.Math,_t=t.Number,dt=t.Object,wt=t.RegExp,jt=t.String,kt=t.TypeError,xt=[],Ct=dt.prototype,Ot=t._,Nt=Ct.toString,Rt=wt("^"+jt(Nt).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),Et=bt.ceil,It=t.clearTimeout,St=bt.floor,At=mt.prototype.toString,Dt=cn(Dt=dt.getPrototypeOf)&&Dt,Tt=Ct.hasOwnProperty,$t=xt.push,Ft=t.setTimeout,Bt=xt.splice,Wt=xt.unshift,qt=function(){
try{var n={},r=cn(r=dt.defineProperty)&&r,t=r(n,n,n)&&r}catch(e){}return t}(),zt=cn(zt=dt.create)&&zt,Lt=cn(Lt=ht.isArray)&&Lt,Pt=t.isFinite,Kt=t.isNaN,Ut=cn(Ut=dt.keys)&&Ut,Mt=bt.max,Vt=bt.min,Gt=t.parseInt,Ht=bt.random,Jt={};Jt[$]=ht,Jt[F]=gt,Jt[B]=yt,Jt[W]=mt,Jt[z]=dt,Jt[q]=_t,Jt[L]=wt,Jt[P]=jt,g.prototype=h.prototype;var Qt=h.support={};Qt.funcDecomp=!cn(t.WinRTError)&&I.test(s),Qt.funcNames="string"==typeof mt.name,h.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:N,
variable:"",imports:{_:h}},zt||(J=function(){function n(){}return function(r){if(Sn(r)){n.prototype=r;var e=new n;n.prototype=null}return e||t.Object()}}());var Xt=qt?function(n,r){M.value=r,qt(n,"__bindData__",M),M.value=null}:rt,Yt=Lt||function(n){return n&&"object"==typeof n&&"number"==typeof n.length&&Nt.call(n)==$||!1},Zt=function(n){var r,t=n,e=[];if(!t)return e;if(!V[typeof n])return e;for(r in t)Tt.call(t,r)&&e.push(r);return e},ne=Ut?function(n){return Sn(n)?Ut(n):[]}:Zt,re={"&":"&amp;",
"<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},te=kn(re),ee=wt("("+ne(te).join("|")+")","g"),ue=wt("["+ne(re).join("")+"]","g"),oe=function(n,r,t){var e,u=n,o=u;if(!u)return o;var a=arguments,i=0,f="number"==typeof t?2:a.length;if(f>3&&"function"==typeof a[f-2])var l=Q(a[--f-1],a[f--],2);else f>2&&"function"==typeof a[f-1]&&(l=a[--f]);for(;++i<f;)if(u=a[i],u&&V[typeof u])for(var c=-1,p=V[typeof u]&&ne(u),s=p?p.length:0;++c<s;)e=p[c],o[e]=l?l(o[e],u[e]):u[e];return o},ae=function(n,r,t){var e,u=n,o=u;
if(!u)return o;for(var a=arguments,i=0,f="number"==typeof t?2:a.length;++i<f;)if(u=a[i],u&&V[typeof u])for(var l=-1,c=V[typeof u]&&ne(u),p=c?c.length:0;++l<p;)e=c[l],"undefined"==typeof o[e]&&(o[e]=u[e]);return o},ie=function(n,r,t){var e,u=n,o=u;if(!u)return o;if(!V[typeof u])return o;r=r&&"undefined"==typeof t?r:Q(r,t,3);for(e in u)if(r(u[e],e,n)===!1)return o;return o},fe=function(n,r,t){var e,u=n,o=u;if(!u)return o;if(!V[typeof u])return o;r=r&&"undefined"==typeof t?r:Q(r,t,3);for(var a=-1,i=V[typeof u]&&ne(u),f=i?i.length:0;++a<f;)if(e=i[a],
r(u[e],e,n)===!1)return o;return o},le=Dt?function(n){if(!n||Nt.call(n)!=z)return!1;var r=n.valueOf,t=cn(r)&&(t=Dt(r))&&Dt(t);return t?n==t||Dt(n)==t:pn(n)}:pn,ce=on(function(n,r,t){Tt.call(n,t)?n[t]++:n[t]=1}),pe=on(function(n,r,t){(Tt.call(n,t)?n[t]:n[t]=[]).push(r)}),se=on(function(n,r,t){n[t]=r}),ve=nr,he=Hn,ge=cn(ge=yt.now)&&ge||function(){return(new yt).getTime()},ye=8==Gt(d+"08")?Gt:function(n,r){return Gt(Fn(n)?n.replace(R,""):n,r||0)};return h.after=Tr,h.assign=oe,h.at=Mn,h.bind=$r,h.bindAll=Fr,
h.bindKey=Br,h.chain=lt,h.compact=sr,h.compose=Wr,h.constant=Jr,h.countBy=ce,h.create=yn,h.createCallback=Qr,h.curry=qr,h.debounce=zr,h.defaults=ae,h.defer=Lr,h.delay=Pr,h.difference=vr,h.filter=Hn,h.flatten=mr,h.forEach=Xn,h.forEachRight=Yn,h.forIn=ie,h.forInRight=_n,h.forOwn=fe,h.forOwnRight=dn,h.functions=wn,h.groupBy=pe,h.indexBy=se,h.initial=_r,h.intersection=dr,h.invert=kn,h.invoke=Zn,h.keys=ne,h.map=nr,h.mapValues=Wn,h.max=rr,h.memoize=Kr,h.merge=qn,h.min=tr,h.omit=zn,h.once=Ur,h.pairs=Ln,
h.partial=Mr,h.partialRight=Vr,h.pick=Pn,h.pluck=ve,h.property=tt,h.pull=kr,h.range=xr,h.reject=or,h.remove=Cr,h.rest=Or,h.shuffle=ir,h.sortBy=cr,h.tap=ct,h.throttle=Gr,h.times=at,h.toArray=pr,h.transform=Kn,h.union=Rr,h.uniq=Er,h.values=Un,h.where=he,h.without=Ir,h.wrap=Hr,h.xor=Sr,h.zip=Ar,h.zipObject=Dr,h.collect=nr,h.drop=Or,h.each=Xn,h.eachRight=Yn,h.extend=oe,h.methods=wn,h.object=Dr,h.select=Hn,h.tail=Or,h.unique=Er,h.unzip=Ar,Zr(h),h.clone=hn,h.cloneDeep=gn,h.contains=Vn,h.escape=Xr,h.every=Gn,
h.find=Jn,h.findIndex=hr,h.findKey=mn,h.findLast=Qn,h.findLastIndex=gr,h.findLastKey=bn,h.has=jn,h.identity=Yr,h.indexOf=br,h.isArguments=vn,h.isArray=Yt,h.isBoolean=xn,h.isDate=Cn,h.isElement=On,h.isEmpty=Nn,h.isEqual=Rn,h.isFinite=En,h.isFunction=In,h.isNaN=An,h.isNull=Dn,h.isNumber=Tn,h.isObject=Sn,h.isPlainObject=le,h.isRegExp=$n,h.isString=Fn,h.isUndefined=Bn,h.lastIndexOf=jr,h.mixin=Zr,h.noConflict=nt,h.noop=rt,h.now=ge,h.parseInt=ye,h.random=et,h.reduce=er,h.reduceRight=ur,h.result=ut,h.runInContext=s,
h.size=fr,h.some=lr,h.sortedIndex=Nr,h.template=ot,h.unescape=it,h.uniqueId=ft,h.all=Gn,h.any=lr,h.detect=Jn,h.findWhere=Jn,h.foldl=er,h.foldr=ur,h.include=Vn,h.inject=er,Zr(function(){var n={};return fe(h,function(r,t){h.prototype[t]||(n[t]=r)}),n}(),!1),h.first=yr,h.last=wr,h.sample=ar,h.take=yr,h.head=yr,fe(h,function(n,r){var t="sample"!==r;h.prototype[r]||(h.prototype[r]=function(r,e){var u=this.__chain__,o=n(this.__wrapped__,r,e);return u||null!=r&&(!e||t&&"function"==typeof r)?new g(o,u):o;
})}),h.VERSION="2.4.2",h.prototype.chain=pt,h.prototype.toString=st,h.prototype.value=vt,h.prototype.valueOf=vt,Xn(["join","pop","shift"],function(n){var r=xt[n];h.prototype[n]=function(){var n=this.__chain__,t=r.apply(this.__wrapped__,arguments);return n?new g(t,n):t}}),Xn(["push","reverse","sort","unshift"],function(n){var r=xt[n];h.prototype[n]=function(){return r.apply(this.__wrapped__,arguments),this}}),Xn(["concat","slice","splice"],function(n){var r=xt[n];h.prototype[n]=function(){return new g(r.apply(this.__wrapped__,arguments),this.__chain__);
}}),h}var v,h=[],g=[],y=0,m=+new Date+"",b=75,_=40,d=" \f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000",w=/\b__p \+= '';/g,j=/\b(__p \+=) '' \+/g,k=/(__e\(.*?\)|\b__t\)) \+\n'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,N=/<%=([\s\S]+?)%>/g,R=RegExp("^["+d+"]*0+(?=.$)"),E=/($^)/,I=/\bthis\b/,S=/['\n\r\t\u2028\u2029\\]/g,A=["Array","Boolean","Date","Function","Math","Number","Object","RegExp","String","_","attachEvent","clearTimeout","isFinite","isNaN","parseInt","setTimeout"],D=0,T="[object Arguments]",$="[object Array]",F="[object Boolean]",B="[object Date]",W="[object Function]",q="[object Number]",z="[object Object]",L="[object RegExp]",P="[object String]",K={};
K[W]=!1,K[T]=K[$]=K[F]=K[B]=K[q]=K[z]=K[L]=K[P]=!0;var U={leading:!1,maxWait:0,trailing:!1},M={configurable:!1,enumerable:!1,value:null,writable:!1},V={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},G={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},H=V[typeof window]&&window||this,J=V[typeof exports]&&exports&&!exports.nodeType&&exports,Q=V[typeof module]&&module&&!module.nodeType&&module,X=Q&&Q.exports===J&&J,Y=V[typeof global]&&global;!Y||Y.global!==Y&&Y.window!==Y||(H=Y);
var Z=s();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(H._=Z,define(function(){return Z})):J&&Q?X?(Q.exports=Z)._=Z:J._=Z:H._=Z}).call(this);
\ No newline at end of file
/**
* @license
* Lo-Dash 2.4.2 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
*/
;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++t<e;)if(n[t]===r)return t;return-1}function r(n,r){for(var t=n.m,e=r.m,u=-1,o=t.length;++u<o;){var i=t[u],f=e[u];if(i!==f){if(i>f||typeof i=="undefined")return 1;if(i<f||typeof f=="undefined")return-1}}return n.n-r.n}function t(n){return"\\"+yr[n]}function e(n,r,t){r||(r=0),typeof t=="undefined"&&(t=n?n.length:0);var e=-1;t=t-r||0;for(var u=Array(0>t?0:t);++e<t;)u[e]=n[r+e];return u}function u(n){return n instanceof u?n:new o(n)}function o(n,r){this.__chain__=!!r,this.__wrapped__=n
}function i(n){function r(){if(u){var n=e(u);Rr.apply(n,arguments)}if(this instanceof r){var i=f(t.prototype),n=t.apply(i,n||arguments);return O(n)?n:i}return t.apply(o,n||arguments)}var t=n[0],u=n[2],o=n[4];return r}function f(n){return O(n)?Br(n):{}}function a(n,r,t){if(typeof n!="function")return Y;if(typeof r=="undefined"||!("prototype"in n))return n;switch(t){case 1:return function(t){return n.call(r,t)};case 2:return function(t,e){return n.call(r,t,e)};case 3:return function(t,e,u){return n.call(r,t,e,u)
};case 4:return function(t,e,u,o){return n.call(r,t,e,u,o)}}return L(n,r)}function l(n){function r(){var n=p?a:this;if(o){var y=e(o);Rr.apply(y,arguments)}return(i||g)&&(y||(y=e(arguments)),i&&Rr.apply(y,i),g&&y.length<c)?(u|=16,l([t,h?u:-4&u,y,null,a,c])):(y||(y=arguments),s&&(t=n[v]),this instanceof r?(n=f(t.prototype),y=t.apply(n,y),O(y)?y:n):t.apply(n,y))}var t=n[0],u=n[1],o=n[2],i=n[3],a=n[4],c=n[5],p=1&u,s=2&u,g=4&u,h=8&u,v=t;return r}function c(n,r){for(var t=-1,e=m(),u=n?n.length:0,o=[];++t<u;){var i=n[t];
0>e(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e<u;){var i=n[e];if(i&&typeof i=="object"&&typeof i.length=="number"&&(Cr(i)||b(i))){r||(i=p(i,r,t));var f=-1,a=i.length,l=o.length;for(o.length+=a;++f<a;)o[l++]=i[f]}else t||o.push(i)}return o}function s(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(n===n&&!(n&&vr[typeof n]||r&&vr[typeof r]))return false;if(null==n||null==r)return n===r;var o=Er.call(n),i=Er.call(r);if(o!=i)return false;switch(o){case lr:case cr:return+n==+r;
case pr:return n!=+n?r!=+r:0==n?1/n==1/r:n==+r;case gr:case hr:return n==r+""}if(i=o==ar,!i){var f=n instanceof u,a=r instanceof u;if(f||a)return s(f?n.__wrapped__:n,a?r.__wrapped__:r,t,e);if(o!=sr)return false;if(o=n.constructor,f=r.constructor,o!=f&&!(A(o)&&o instanceof o&&A(f)&&f instanceof f)&&"constructor"in n&&"constructor"in r)return false}for(t||(t=[]),e||(e=[]),o=t.length;o--;)if(t[o]==n)return e[o]==r;var l=true,c=0;if(t.push(n),e.push(r),i){if(c=r.length,l=c==n.length)for(;c--&&(l=s(n[c],r[c],t,e)););}else Kr(r,function(r,u,o){return Nr.call(o,u)?(c++,!(l=Nr.call(n,u)&&s(n[u],r,t,e))&&er):void 0
}),l&&Kr(n,function(n,r,t){return Nr.call(t,r)?!(l=-1<--c)&&er:void 0});return t.pop(),e.pop(),l}function g(n,r,t){for(var e=-1,u=m(),o=n?n.length:0,i=[],f=t?[]:i;++e<o;){var a=n[e],l=t?t(a,e,n):a;(r?!e||f[f.length-1]!==l:0>u(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=X(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++e<o;){var i=r[e];n(u,i,t(i,e,r),r)}else Lr(r,function(r,e,o){n(u,r,t(r,e,o),o)});return u}}function v(n,r,t,e,u,o){var f=16&r,a=32&r;
if(!(2&r||A(n)))throw new TypeError;return f&&!t.length&&(r&=-17,t=false),a&&!e.length&&(r&=-33,e=false),(1==r||17===r?i:l)([n,r,t,e,u,o])}function y(n){return Vr[n]}function m(){var r=(r=u.indexOf)===G?n:r;return r}function _(n){return typeof n=="function"&&Ar.test(n)}function d(n){return Gr[n]}function b(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Er.call(n)==fr||false}function w(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)n[u]=e[u]}return n
}function j(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)"undefined"==typeof n[u]&&(n[u]=e[u])}return n}function x(n){var r=[];return Kr(n,function(n,t){A(n)&&r.push(t)}),r.sort()}function T(n){for(var r=-1,t=Ur(n),e=t.length,u={};++r<e;){var o=t[r];u[n[o]]=o}return u}function E(n){if(!n)return true;if(Cr(n)||N(n))return!n.length;for(var r in n)if(Nr.call(n,r))return false;return true}function A(n){return typeof n=="function"}function O(n){return!(!n||!vr[typeof n])
}function S(n){return typeof n=="number"||n&&typeof n=="object"&&Er.call(n)==pr||false}function N(n){return typeof n=="string"||n&&typeof n=="object"&&Er.call(n)==hr||false}function R(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];return u}function k(n,r){var t=m(),e=n?n.length:0,u=false;return e&&typeof e=="number"?u=-1<t(n,r):Lr(n,function(n){return(u=n===r)&&er}),u}function B(n,r,t){var e=true;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&(e=!!r(n[t],t,n)););else Lr(n,function(n,t,u){return!(e=!!r(n,t,u))&&er
});return e}function F(n,r,t){var e=[];r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u;){var o=n[t];r(o,t,n)&&e.push(o)}else Lr(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function q(n,r,t){r=X(r,t,3),t=-1;var e=n?n.length:0;if(typeof e!="number"){var u;return Lr(n,function(n,t,e){return r(n,t,e)?(u=n,er):void 0}),u}for(;++t<e;){var o=n[t];if(r(o,t,n))return o}}function D(n,r,t){var e=-1,u=n?n.length:0;if(r=r&&typeof t=="undefined"?r:a(r,t,3),typeof u=="number")for(;++e<u&&r(n[e],e,n)!==er;);else Lr(n,r)
}function I(n,r){var t=n?n.length:0;if(typeof t=="number")for(;t--&&false!==r(n[t],t,n););else{var e=Ur(n),t=e.length;Lr(n,function(n,u,o){return u=e?e[--t]:--t,false===r(o[u],u,o)&&er})}}function M(n,r,t){var e=-1,u=n?n.length:0;if(r=X(r,t,3),typeof u=="number")for(var o=Array(u);++e<u;)o[e]=r(n[e],e,n);else o=[],Lr(n,function(n,t,u){o[++e]=r(n,t,u)});return o}function $(n,r,t){var e=-1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t>u&&(u=t);
else r=X(r,t,3),D(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=X(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++o<i;)t=r(t,n[o],o,n);else Lr(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)});return t}function z(n,r,t,e){var u=3>arguments.length;return r=X(r,e,4),I(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return D(n,function(n){var t;t=++r,t=0+Sr(Wr()*(t-0+1)),e[r]=e[t],e[t]=n
}),e}function P(n,r,t){var e;r=X(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&!(e=r(n[t],t,n)););else Lr(n,function(n,t,u){return(e=r(n,t,u))&&er});return!!e}function U(n,r,t){return t&&E(r)?rr:(t?q:F)(n,r)}function V(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=-1;for(r=X(r,t,3);++i<o&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[0]:rr;return e(n,0,$r(Mr(0,u),o))}function G(r,t,e){if(typeof e=="number"){var u=r?r.length:0;e=0>e?Mr(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1;
return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=X(r,t,3);++o<i&&r(n[o],o,n);)u++}else u=null==r||t?1:Mr(0,r);return e(n,u)}function J(n,r,t,e){var u=0,o=n?n.length:u;for(t=t?X(t,e,1):Y,r=t(r);u<o;)e=u+o>>>1,t(n[e])<r?u=e+1:o=e;return u}function K(n,r,t,e){return typeof r!="boolean"&&null!=r&&(e=t,t=typeof r!="function"&&e&&e[r]===n?null:r,r=false),null!=t&&(t=X(t,e,3)),g(n,r,t)}function L(n,r){return 2<arguments.length?v(n,17,e(arguments,2),null,r):v(n,1,null,null,r)
}function Q(n,r,t){var e,u,o,i,f,a,l,c=0,p=false,s=true;if(!A(n))throw new TypeError;if(r=Mr(0,r)||0,true===t)var g=true,s=false;else O(t)&&(g=t.leading,p="maxWait"in t&&(Mr(r,t.maxWait)||0),s="trailing"in t?t.trailing:s);var h=function(){var t=r-(nt()-i);0<t?a=setTimeout(h,t):(u&&clearTimeout(u),t=l,u=a=l=rr,t&&(c=nt(),o=n.apply(f,e),a||u||(e=f=null)))},v=function(){a&&clearTimeout(a),u=a=l=rr,(s||p!==r)&&(c=nt(),o=n.apply(f,e),a||u||(e=f=null))};return function(){if(e=arguments,i=nt(),f=this,l=s&&(a||!g),false===p)var t=g&&!a;
else{u||g||(c=i);var y=p-(i-c),m=0>=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o}}function X(n,r,t){var e=typeof n;if(null==n||"function"==e)return a(n,r,t);if("object"!=e)return nr(n);var u=Ur(n);return function(r){for(var t=u.length,e=false;t--&&(e=r[u[t]]===n[u[t]]););return e}}function Y(n){return n}function Z(n){D(x(n),function(r){var t=u[r]=n[r];u.prototype[r]=function(){var n=[this.__wrapped__];
return Rr.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}function nr(n){return function(r){return r[n]}}var rr,tr=0,er={},ur=+new Date+"",or=/($^)/,ir=/['\n\r\t\u2028\u2029\\]/g,fr="[object Arguments]",ar="[object Array]",lr="[object Boolean]",cr="[object Date]",pr="[object Number]",sr="[object Object]",gr="[object RegExp]",hr="[object String]",vr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},yr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},mr=vr[typeof window]&&window||this,_r=vr[typeof exports]&&exports&&!exports.nodeType&&exports,dr=vr[typeof module]&&module&&!module.nodeType&&module,br=dr&&dr.exports===_r&&_r,wr=vr[typeof global]&&global;
!wr||wr.global!==wr&&wr.window!==wr||(mr=wr);var jr=[],xr=Object.prototype,Tr=mr._,Er=xr.toString,Ar=RegExp("^"+(Er+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),Or=Math.ceil,Sr=Math.floor,Nr=xr.hasOwnProperty,Rr=jr.push,kr=xr.propertyIsEnumerable,Br=_(Br=Object.create)&&Br,Fr=_(Fr=Array.isArray)&&Fr,qr=mr.isFinite,Dr=mr.isNaN,Ir=_(Ir=Object.keys)&&Ir,Mr=Math.max,$r=Math.min,Wr=Math.random;o.prototype=u.prototype;var zr={};!function(){var n={0:1,length:1};zr.spliceObjects=(jr.splice.call(n,0,1),!n[0])
}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Br||(f=function(){function n(){}return function(r){if(O(r)){n.prototype=r;var t=new n;n.prototype=null}return t||mr.Object()}}()),b(arguments)||(b=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Nr.call(n,"callee")&&!kr.call(n,"callee")||false});var Cr=Fr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Er.call(n)==ar||false},Pr=function(n){var r,t=[];
if(!n||!vr[typeof n])return t;for(r in n)Nr.call(n,r)&&t.push(r);return t},Ur=Ir?function(n){return O(n)?Ir(n):[]}:Pr,Vr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},Gr=T(Vr),Hr=RegExp("("+Ur(Gr).join("|")+")","g"),Jr=RegExp("["+Ur(Vr).join("")+"]","g"),Kr=function(n,r){var t;if(!n||!vr[typeof n])return n;for(t in n)if(r(n[t],t,n)===er)break;return n},Lr=function(n,r){var t;if(!n||!vr[typeof n])return n;for(t in n)if(Nr.call(n,t)&&r(n[t],t,n)===er)break;return n};A(/x/)&&(A=function(n){return typeof n=="function"&&"[object Function]"==Er.call(n)
});var Qr=h(function(n,r,t){Nr.call(n,t)?n[t]++:n[t]=1}),Xr=h(function(n,r,t){(Nr.call(n,t)?n[t]:n[t]=[]).push(r)}),Yr=h(function(n,r,t){n[t]=r}),Zr=M,nt=_(nt=Date.now)&&nt||function(){return(new Date).getTime()};u.after=function(n,r){if(!A(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1<arguments.length?p(arguments,true,false,1):x(n),t=-1,e=r.length;++t<e;){var u=r[t];n[u]=v(n[u],1,null,null,n)}return n},u.chain=function(n){return n=new o(n),n.__chain__=true,n
},u.compact=function(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e},u.compose=function(){for(var n=arguments,r=n.length;r--;)if(!A(n[r]))throw new TypeError;return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}},u.countBy=Qr,u.debounce=Q,u.defaults=j,u.defer=function(n){if(!A(n))throw new TypeError;var r=e(arguments,1);return setTimeout(function(){n.apply(rr,r)},1)},u.delay=function(n,r){if(!A(n))throw new TypeError;var t=e(arguments,2);
return setTimeout(function(){n.apply(rr,t)},r)},u.difference=function(n){return c(n,p(arguments,true,true,1))},u.filter=F,u.flatten=function(n,r){return p(n,r)},u.forEach=D,u.functions=x,u.groupBy=Xr,u.indexBy=Yr,u.initial=function(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else u=null==r||t?1:r||u;return e(n,0,$r(Mr(0,o-u),o))},u.intersection=function(){for(var n=[],r=-1,t=arguments.length;++r<t;){var e=arguments[r];(Cr(e)||b(e))&&n.push(e)
}var u=n[0],o=-1,i=m(),f=u?u.length:0,a=[];n:for(;++o<f;)if(e=u[o],0>i(a,e)){for(r=t;--r;)if(0>i(n[r],e))continue n;a.push(e)}return a},u.invert=T,u.invoke=function(n,r){var t=e(arguments,2),u=-1,o=typeof r=="function",i=n?n.length:0,f=Array(typeof i=="number"?i:0);return D(n,function(n){f[++u]=(o?r:n[r]).apply(n,t)}),f},u.keys=Ur,u.map=M,u.max=$,u.memoize=function(n,r){var t={};return function(){var e=r?r.apply(this,arguments):ur+arguments[0];return Nr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)
}},u.min=function(n,r,t){var e=1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t<u&&(u=t);else r=X(r,t,3),D(n,function(n,t,o){t=r(n,t,o),t<e&&(e=t,u=n)});return u},u.omit=function(n){var r=[];Kr(n,function(n,t){r.push(t)});for(var r=c(r,p(arguments,true,false,1)),t=-1,e=r.length,u={};++t<e;){var o=r[t];u[o]=n[o]}return u},u.once=function(n){var r,t;if(!A(n))throw new TypeError;return function(){return r?t:(r=true,t=n.apply(this,arguments),n=null,t)
}},u.pairs=function(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;){var o=t[r];u[r]=[o,n[o]]}return u},u.partial=function(n){return v(n,16,e(arguments,1))},u.pick=function(n){for(var r=-1,t=p(arguments,true,false,1),e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u},u.pluck=Zr,u.range=function(n,r,t){n=+n||0,t=+t||1,null==r&&(r=n,n=0);var e=-1;r=Mr(0,Or((r-n)/t));for(var u=Array(r);++e<r;)u[e]=n,n+=t;return u},u.reject=function(n,r,t){return r=X(r,t,3),F(n,function(n,t,e){return!r(n,t,e)
})},u.rest=H,u.shuffle=C,u.sortBy=function(n,t,e){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);for(t=X(t,e,3),D(n,function(n,r,e){i[++u]={m:[t(n,r,e)],n:u,o:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].o;return i},u.tap=function(n,r){return r(n),n},u.throttle=function(n,r,t){var e=true,u=true;if(!A(n))throw new TypeError;return false===t?e=false:O(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),t={},t.leading=e,t.maxWait=r,t.trailing=u,Q(n,r,t)},u.times=function(n,r,t){n=-1<(n=+n)?n:0;
var e=-1,u=Array(n);for(r=a(r,t,1);++e<n;)u[e]=r(e);return u},u.toArray=function(n){return Cr(n)?e(n):n&&typeof n.length=="number"?M(n):R(n)},u.union=function(){return g(p(arguments,true,true))},u.uniq=K,u.values=R,u.where=U,u.without=function(n){return c(n,e(arguments,1))},u.wrap=function(n,r){return v(r,16,[n])},u.zip=function(){for(var n=-1,r=$(Zr(arguments,"length")),t=Array(0>r?0:r);++n<r;)t[n]=Zr(arguments,n);return t},u.collect=M,u.drop=H,u.each=D,u.extend=w,u.methods=x,u.object=function(n,r){var t=-1,e=n?n.length:0,u={};
for(r||!e||Cr(n[0])||(r=[]);++t<e;){var o=n[t];r?u[o]=r[t]:o&&(u[o[0]]=o[1])}return u},u.select=F,u.tail=H,u.unique=K,u.clone=function(n){return O(n)?Cr(n)?e(n):w({},n):n},u.contains=k,u.escape=function(n){return null==n?"":(n+"").replace(Jr,y)},u.every=B,u.find=q,u.has=function(n,r){return n?Nr.call(n,r):false},u.identity=Y,u.indexOf=G,u.isArguments=b,u.isArray=Cr,u.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&Er.call(n)==lr||false},u.isDate=function(n){return n&&typeof n=="object"&&Er.call(n)==cr||false
},u.isElement=function(n){return n&&1===n.nodeType||false},u.isEmpty=E,u.isEqual=function(n,r){return s(n,r)},u.isFinite=function(n){return qr(n)&&!Dr(parseFloat(n))},u.isFunction=A,u.isNaN=function(n){return S(n)&&n!=+n},u.isNull=function(n){return null===n},u.isNumber=S,u.isObject=O,u.isRegExp=function(n){return n&&vr[typeof n]&&Er.call(n)==gr||false},u.isString=N,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e;
return-1},u.mixin=Z,u.noConflict=function(){return mr._=Tr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Sr(Wr()*(r-n+1))},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return A(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Ur(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=j({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||or).source+"|"+(e.interpolate||or).source+"|"+(e.evaluate||or).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(ir,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r
}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,d)},u.uniqueId=function(n){var r=++tr+"";return n?n+r:r},u.all=B,u.any=P,u.detect=q,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=k,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0;
if(typeof r!="number"&&null!=r){var i=o;for(r=X(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:rr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=R(n)),null==r||t?n?n[0+Sr(Wr()*(n.length-1-0+1))]:rr:(n=C(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.4.2",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},D("pop push reverse shift sort splice unshift".split(" "),function(n){var r=jr[n];
u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this}}),D(["concat","join","slice"],function(n){var r=jr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(mr._=u, define(function(){return u})):_r&&dr?br?(dr.exports=u)._=u:_r._=u:mr._=u}).call(this);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"_from": "lodash@^2.4.1",
"_id": "lodash@2.4.2",
"_inBundle": false,
"_integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
"_location": "/lodash",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "lodash@^2.4.1",
"name": "lodash",
"escapedName": "lodash",
"rawSpec": "^2.4.1",
"saveSpec": null,
"fetchSpec": "^2.4.1"
},
"_requiredBy": [
"#DEV:/"
],
"_resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
"_shasum": "fadd834b9683073da179b3eae6d9c0d15053f73e",
"_spec": "lodash@^2.4.1",
"_where": "/Users/jmorrell/workspace/heroku-buildpack-nodejs/test/fixtures/dependencies-modules-checked-in-with-devdependencies",
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
"url": "http://allyoucanleet.com/"
},
"bugs": {
"url": "https://github.com/lodash/lodash/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
"url": "http://allyoucanleet.com/"
},
{
"name": "Blaine Bublitz",
"email": "blaine@iceddev.com",
"url": "http://www.iceddev.com/"
},
{
"name": "Kit Cambridge",
"email": "github@kitcambridge.be",
"url": "http://kitcambridge.be/"
},
{
"name": "Mathias Bynens",
"email": "mathias@qiwi.be",
"url": "http://mathiasbynens.be/"
}
],
"deprecated": false,
"description": "A utility library delivering consistency, customization, performance, & extras.",
"engines": [
"node",
"rhino"
],
"files": [
"LICENSE.txt",
"lodash.js",
"dist/lodash.js",
"dist/lodash.min.js",
"dist/lodash.compat.js",
"dist/lodash.compat.min.js",
"dist/lodash.underscore.js",
"dist/lodash.underscore.min.js"
],
"homepage": "http://lodash.com/",
"jam": {
"main": "dist/lodash.compat.js",
"include": [
"LICENSE.txt",
"dist/lodash.js",
"dist/lodash.min.js",
"dist/lodash.compat.js",
"dist/lodash.compat.min.js",
"dist/lodash.underscore.js",
"dist/lodash.underscore.min.js"
]
},
"keywords": [
"amd",
"browser",
"client",
"customize",
"functional",
"server",
"util"
],
"license": "MIT",
"main": "dist/lodash.js",
"name": "lodash",
"repository": {
"type": "git",
"url": "git+https://github.com/lodash/lodash.git"
},
"version": "2.4.2",
"volo": {
"type": "directory",
"ignore": [
".*",
"*.custom.*",
"*.min.*",
"*.template.*",
"*.map",
"*.md",
"lodash.js",
"index.js",
"bower.json",
"component.json",
"doc",
"modularize",
"node_modules",
"perf",
"test",
"vendor"
]
}
}
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
http://www.opensource.org/licenses/mit-license.php
Copyright 2010 James Halliday (mail@substack.net)
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.
var traverse = require('traverse');
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
console.dir(scrubbed);
console.dir(callbacks);
var traverse = require('traverse');
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 },
};
var leaves = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
console.dir(leaves);
var traverse = require('traverse');
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
console.dir(obj);
// scrub out circular references
var traverse = require('traverse');
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
obj.c.push(obj);
var scrubbed = traverse(obj).map(function (x) {
if (this.circular) this.remove()
});
console.dir(scrubbed);
#!/usr/bin/env node
var traverse = require('traverse');
var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var s = '';
traverse(obj).forEach(function to_s (node) {
if (Array.isArray(node)) {
this.before(function () { s += '[' });
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += ']' });
}
else if (typeof node == 'object') {
this.before(function () { s += '{' });
this.pre(function (x, key) {
to_s(key);
s += ':';
});
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += '}' });
}
else if (typeof node == 'string') {
s += '"' + node.toString().replace(/"/g, '\\"') + '"';
}
else if (typeof node == 'function') {
s += 'null';
}
else {
s += node.toString();
}
});
console.log('JSON.stringify: ' + JSON.stringify(obj));
console.log('this stringify: ' + s);
var traverse = module.exports = function (obj) {
return new Traverse(obj);
};
function Traverse (obj) {
this.value = obj;
}
Traverse.prototype.get = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
node = undefined;
break;
}
node = node[key];
}
return node;
};
Traverse.prototype.has = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
return false;
}
node = node[key];
}
return true;
};
Traverse.prototype.set = function (ps, value) {
var node = this.value;
for (var i = 0; i < ps.length - 1; i ++) {
var key = ps[i];
if (!hasOwnProperty.call(node, key)) node[key] = {};
node = node[key];
}
node[ps[i]] = value;
return value;
};
Traverse.prototype.map = function (cb) {
return walk(this.value, cb, true);
};
Traverse.prototype.forEach = function (cb) {
this.value = walk(this.value, cb, false);
return this.value;
};
Traverse.prototype.reduce = function (cb, init) {
var skip = arguments.length === 1;
var acc = skip ? this.value : init;
this.forEach(function (x) {
if (!this.isRoot || !skip) {
acc = cb.call(this, acc, x);
}
});
return acc;
};
Traverse.prototype.paths = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.path);
});
return acc;
};
Traverse.prototype.nodes = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.node);
});
return acc;
};
Traverse.prototype.clone = function () {
var parents = [], nodes = [];
return (function clone (src) {
for (var i = 0; i < parents.length; i++) {
if (parents[i] === src) {
return nodes[i];
}
}
if (typeof src === 'object' && src !== null) {
var dst = copy(src);
parents.push(src);
nodes.push(dst);
forEach(objectKeys(src), function (key) {
dst[key] = clone(src[key]);
});
parents.pop();
nodes.pop();
return dst;
}
else {
return src;
}
})(this.value);
};
function walk (root, cb, immutable) {
var path = [];
var parents = [];
var alive = true;
return (function walker (node_) {
var node = immutable ? copy(node_) : node_;
var modifiers = {};
var keepGoing = true;
var state = {
node : node,
node_ : node_,
path : [].concat(path),
parent : parents[parents.length - 1],
parents : parents,
key : path.slice(-1)[0],
isRoot : path.length === 0,
level : path.length,
circular : null,
update : function (x, stopHere) {
if (!state.isRoot) {
state.parent.node[state.key] = x;
}
state.node = x;
if (stopHere) keepGoing = false;
},
'delete' : function (stopHere) {
delete state.parent.node[state.key];
if (stopHere) keepGoing = false;
},
remove : function (stopHere) {
if (isArray(state.parent.node)) {
state.parent.node.splice(state.key, 1);
}
else {
delete state.parent.node[state.key];
}
if (stopHere) keepGoing = false;
},
keys : null,
before : function (f) { modifiers.before = f },
after : function (f) { modifiers.after = f },
pre : function (f) { modifiers.pre = f },
post : function (f) { modifiers.post = f },
stop : function () { alive = false },
block : function () { keepGoing = false }
};
if (!alive) return state;
function updateState() {
if (typeof state.node === 'object' && state.node !== null) {
if (!state.keys || state.node_ !== state.node) {
state.keys = objectKeys(state.node)
}
state.isLeaf = state.keys.length == 0;
for (var i = 0; i < parents.length; i++) {
if (parents[i].node_ === node_) {
state.circular = parents[i];
break;
}
}
}
else {
state.isLeaf = true;
state.keys = null;
}
state.notLeaf = !state.isLeaf;
state.notRoot = !state.isRoot;
}
updateState();
// use return values to update if defined
var ret = cb.call(state, state.node);
if (ret !== undefined && state.update) state.update(ret);
if (modifiers.before) modifiers.before.call(state, state.node);
if (!keepGoing) return state;
if (typeof state.node == 'object'
&& state.node !== null && !state.circular) {
parents.push(state);
updateState();
forEach(state.keys, function (key, i) {
path.push(key);
if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
var child = walker(state.node[key]);
if (immutable && hasOwnProperty.call(state.node, key)) {
state.node[key] = child.node;
}
child.isLast = i == state.keys.length - 1;
child.isFirst = i == 0;
if (modifiers.post) modifiers.post.call(state, child);
path.pop();
});
parents.pop();
}
if (modifiers.after) modifiers.after.call(state, state.node);
return state;
})(root).node;
}
function copy (src) {
if (typeof src === 'object' && src !== null) {
var dst;
if (isArray(src)) {
dst = [];
}
else if (isDate(src)) {
dst = new Date(src.getTime ? src.getTime() : src);
}
else if (isRegExp(src)) {
dst = new RegExp(src);
}
else if (isError(src)) {
dst = { message: src.message };
}
else if (isBoolean(src)) {
dst = new Boolean(src);
}
else if (isNumber(src)) {
dst = new Number(src);
}
else if (isString(src)) {
dst = new String(src);
}
else if (Object.create && Object.getPrototypeOf) {
dst = Object.create(Object.getPrototypeOf(src));
}
else if (src.constructor === Object) {
dst = {};
}
else {
var proto =
(src.constructor && src.constructor.prototype)
|| src.__proto__
|| {}
;
var T = function () {};
T.prototype = proto;
dst = new T;
}
forEach(objectKeys(src), function (key) {
dst[key] = src[key];
});
return dst;
}
else return src;
}
var objectKeys = Object.keys || function keys (obj) {
var res = [];
for (var key in obj) res.push(key)
return res;
};
function toS (obj) { return Object.prototype.toString.call(obj) }
function isDate (obj) { return toS(obj) === '[object Date]' }
function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
function isError (obj) { return toS(obj) === '[object Error]' }
function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
function isNumber (obj) { return toS(obj) === '[object Number]' }
function isString (obj) { return toS(obj) === '[object String]' }
var isArray = Array.isArray || function isArray (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
var forEach = function (xs, fn) {
if (xs.forEach) return xs.forEach(fn)
else for (var i = 0; i < xs.length; i++) {
fn(xs[i], i, xs);
}
};
forEach(objectKeys(Traverse.prototype), function (key) {
traverse[key] = function (obj) {
var args = [].slice.call(arguments, 1);
var t = new Traverse(obj);
return t[key].apply(t, args);
};
});
var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
return key in obj;
};
{
"_from": "traverse@>=0.2.4",
"_id": "traverse@0.6.6",
"_inBundle": false,
"_integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
"_location": "/traverse",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "traverse@>=0.2.4",
"name": "traverse",
"escapedName": "traverse",
"rawSpec": ">=0.2.4",
"saveSpec": null,
"fetchSpec": ">=0.2.4"
},
"_requiredBy": [
"/hashish"
],
"_resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
"_shasum": "cbdf560fd7b9af632502fed40f918c157ea97137",
"_spec": "traverse@>=0.2.4",
"_where": "/Users/jmorrell/workspace/heroku-buildpack-nodejs/test/fixtures/dependencies-modules-checked-in-with-devdependencies/node_modules/hashish",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/js-traverse/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "traverse and transform objects by visiting every node on a recursive walk",
"devDependencies": {
"tape": "~1.0.4"
},
"directories": {
"example": "example",
"test": "test"
},
"homepage": "https://github.com/substack/js-traverse",
"keywords": [
"traverse",
"walk",
"recursive",
"map",
"forEach",
"deep",
"clone"
],
"license": "MIT",
"main": "index.js",
"name": "traverse",
"repository": {
"type": "git",
"url": "git://github.com/substack/js-traverse.git"
},
"scripts": {
"test": "tape test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": {
"iexplore": [
"6.0",
"7.0",
"8.0",
"9.0"
],
"chrome": [
"10.0",
"20.0"
],
"firefox": [
"10.0",
"15.0"
],
"safari": [
"5.1"
],
"opera": [
"12.0"
]
}
},
"version": "0.6.6"
}
# traverse
Traverse and transform objects by visiting every node on a recursive walk.
[![browser support](http://ci.testling.com/substack/js-traverse.png)](http://ci.testling.com/substack/js-traverse)
[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse)
# examples
## transform negative numbers in-place
negative.js
````javascript
var traverse = require('traverse');
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
console.dir(obj);
````
Output:
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
## collect leaf nodes
leaves.js
````javascript
var traverse = require('traverse');
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 },
};
var leaves = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
console.dir(leaves);
````
Output:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
## scrub circular references
scrub.js:
````javascript
var traverse = require('traverse');
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
obj.c.push(obj);
var scrubbed = traverse(obj).map(function (x) {
if (this.circular) this.remove()
});
console.dir(scrubbed);
````
output:
{ a: 1, b: 2, c: [ 3, 4 ] }
# methods
Each method that takes an `fn` uses the context documented below in the context
section.
## .map(fn)
Execute `fn` for each node in the object and return a new object with the
results of the walk. To update nodes in the result use `this.update(value)`.
## .forEach(fn)
Execute `fn` for each node in the object but unlike `.map()`, when
`this.update()` is called it updates the object in-place.
## .reduce(fn, acc)
For each node in the object, perform a
[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))
with the return value of `fn(acc, node)`.
If `acc` isn't specified, `acc` is set to the root object for the first step
and the root element is skipped.
## .paths()
Return an `Array` of every possible non-cyclic path in the object.
Paths are `Array`s of string keys.
## .nodes()
Return an `Array` of every node in the object.
## .clone()
Create a deep clone of the object.
## .get(path)
Get the element at the array `path`.
## .set(path, value)
Set the element at the array `path` to `value`.
## .has(path)
Return whether the element at the array `path` exists.
# context
Each method that takes a callback has a context (its `this` object) with these
attributes:
## this.node
The present node on the recursive walk
## this.path
An array of string keys from the root to the present node
## this.parent
The context of the node's parent.
This is `undefined` for the root node.
## this.key
The name of the key of the present node in its parent.
This is `undefined` for the root node.
## this.isRoot, this.notRoot
Whether the present node is the root node
## this.isLeaf, this.notLeaf
Whether or not the present node is a leaf node (has no children)
## this.level
Depth of the node within the traversal
## this.circular
If the node equals one of its parents, the `circular` attribute is set to the
context of that parent and the traversal progresses no deeper.
## this.update(value, stopHere=false)
Set a new value for the present node.
All the elements in `value` will be recursively traversed unless `stopHere` is
true.
## this.remove(stopHere=false)
Remove the current element from the output. If the node is in an Array it will
be spliced off. Otherwise it will be deleted from its parent.
## this.delete(stopHere=false)
Delete the current element from its parent in the output. Calls `delete` even on
Arrays.
## this.before(fn)
Call this function before any of the children are traversed.
You can assign into `this.keys` here to traverse in a custom order.
## this.after(fn)
Call this function after any of the children are traversed.
## this.pre(fn)
Call this function before each of the children are traversed.
## this.post(fn)
Call this function after each of the children are traversed.
# install
Using [npm](http://npmjs.org) do:
$ npm install traverse
# license
MIT
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
var util = require('util');
test('circular', function (t) {
t.plan(1);
var obj = { x : 3 };
obj.y = obj;
traverse(obj).forEach(function (x) {
if (this.path.join('') == 'y') {
t.equal(
util.inspect(this.circular.node),
util.inspect(obj)
);
}
});
});
test('deepCirc', function (t) {
t.plan(2);
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
var times = 0;
traverse(obj).forEach(function (x) {
if (this.circular) {
t.same(this.circular.path, []);
t.same(this.path, [ 'y', 2 ]);
}
});
});
test('doubleCirc', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var circs = [];
traverse(obj).forEach(function (x) {
if (this.circular) {
circs.push({ circ : this.circular, self : this, node : x });
}
});
t.same(circs[0].self.path, [ 'x', 3, 2 ]);
t.same(circs[0].circ.path, []);
t.same(circs[1].self.path, [ 'y', 2 ]);
t.same(circs[1].circ.path, []);
t.same(circs.length, 2);
t.end();
});
test('circDubForEach', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
traverse(obj).forEach(function (x) {
if (this.circular) this.update('...');
});
t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
t.end();
});
test('circDubMap', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var c = traverse(obj).map(function (x) {
if (this.circular) {
this.update('...');
}
});
t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
t.end();
});
test('circClone', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var clone = traverse.clone(obj);
t.ok(obj !== clone);
t.ok(clone.y[2] === clone);
t.ok(clone.y[2] !== obj);
t.ok(clone.x[3][2] === clone);
t.ok(clone.x[3][2] !== obj);
t.same(clone.x.slice(0,3), [1,2,3]);
t.same(clone.y.slice(0,2), [4,5]);
t.end();
});
test('circMapScrub', function (t) {
var obj = { a : 1, b : 2 };
obj.c = obj;
var scrubbed = traverse(obj).map(function (node) {
if (this.circular) this.remove();
});
t.same(
Object.keys(scrubbed).sort(),
[ 'a', 'b' ]
);
t.ok(deepEqual(scrubbed, { a : 1, b : 2 }));
t.equal(obj.c, obj);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('dateEach', function (t) {
var obj = { x : new Date, y : 10, z : 5 };
var counts = {};
traverse(obj).forEach(function (node) {
var t = (node instanceof Date && 'Date') || typeof node;
counts[t] = (counts[t] || 0) + 1;
});
t.same(counts, {
object : 1,
Date : 1,
number : 2,
});
t.end();
});
test('dateMap', function (t) {
var obj = { x : new Date, y : 10, z : 5 };
var res = traverse(obj).map(function (node) {
if (typeof node === 'number') this.update(node + 100);
});
t.ok(obj.x !== res.x);
t.same(res, {
x : obj.x,
y : 110,
z : 105,
});
t.end();
});
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('deepDates', function (t) {
t.plan(2);
t.ok(
deepEqual(
{ d : new Date, x : [ 1, 2, 3 ] },
{ d : new Date, x : [ 1, 2, 3 ] }
),
'dates should be equal'
);
var d0 = new Date;
setTimeout(function () {
t.ok(
!deepEqual(
{ d : d0, x : [ 1, 2, 3 ], },
{ d : new Date, x : [ 1, 2, 3 ] }
),
'microseconds should count in date equality'
);
}, 5);
});
test('deepCircular', function (t) {
var a = [1];
a.push(a); // a = [ 1, *a ]
var b = [1];
b.push(a); // b = [ 1, [ 1, *a ] ]
t.ok(
!deepEqual(a, b),
'circular ref mount points count towards equality'
);
var c = [1];
c.push(c); // c = [ 1, *c ]
t.ok(
deepEqual(a, c),
'circular refs are structurally the same here'
);
var d = [1];
d.push(a); // c = [ 1, [ 1, *d ] ]
t.ok(
deepEqual(b, d),
'non-root circular ref structural comparison'
);
t.end();
});
test('deepInstances', function (t) {
t.ok(
!deepEqual([ new Boolean(false) ], [ false ]),
'boolean instances are not real booleans'
);
t.ok(
!deepEqual([ new String('x') ], [ 'x' ]),
'string instances are not real strings'
);
t.ok(
!deepEqual([ new Number(4) ], [ 4 ]),
'number instances are not real numbers'
);
t.ok(
deepEqual([ new RegExp('x') ], [ /x/ ]),
'regexp instances are real regexps'
);
t.ok(
!deepEqual([ new RegExp(/./) ], [ /../ ]),
'these regexps aren\'t the same'
);
t.ok(
!deepEqual(
[ function (x) { return x * 2 } ],
[ function (x) { return x * 2 } ]
),
'functions with the same .toString() aren\'t necessarily the same'
);
var f = function (x) { return x * 2 };
t.ok(
deepEqual([ f ], [ f ]),
'these functions are actually equal'
);
t.end();
});
test('deepEqual', function (t) {
t.ok(
!deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }),
'arrays are not objects'
);
t.end();
});
test('falsy', function (t) {
t.ok(
!deepEqual([ undefined ], [ null ]),
'null is not undefined!'
);
t.ok(
!deepEqual([ null ], [ undefined ]),
'undefined is not null!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'undefined is not null, however deeply!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'null is not undefined, however deeply!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'null is not undefined, however deeply!'
);
t.end();
});
test('deletedArrayEqual', function (t) {
var xs = [ 1, 2, 3, 4 ];
delete xs[2];
var ys = Object.create(Array.prototype);
ys[0] = 1;
ys[1] = 2;
ys[3] = 4;
t.ok(
deepEqual(xs, ys),
'arrays with deleted elements are only equal to'
+ ' arrays with similarly deleted elements'
);
t.ok(
!deepEqual(xs, [ 1, 2, undefined, 4 ]),
'deleted array elements cannot be undefined'
);
t.ok(
!deepEqual(xs, [ 1, 2, null, 4 ]),
'deleted array elements cannot be null'
);
t.end();
});
test('deletedObjectEqual', function (t) {
var obj = { a : 1, b : 2, c : 3 };
delete obj.c;
t.ok(
deepEqual(obj, { a : 1, b : 2 }),
'deleted object elements should not show up'
);
t.ok(
!deepEqual(obj, { a : 1, b : 2, c : undefined }),
'deleted object elements are not undefined'
);
t.ok(
!deepEqual(obj, { a : 1, b : 2, c : null }),
'deleted object elements are not null'
);
t.end();
});
test('emptyKeyEqual', function (t) {
t.ok(!deepEqual(
{ a : 1 }, { a : 1, '' : 55 }
));
t.end();
});
test('deepArguments', function (t) {
t.ok(
!deepEqual(
[ 4, 5, 6 ],
(function () { return arguments })(4, 5, 6)
),
'arguments are not arrays'
);
t.ok(
deepEqual(
(function () { return arguments })(4, 5, 6),
(function () { return arguments })(4, 5, 6)
),
'arguments should equal'
);
t.end();
});
test('deepUn', function (t) {
t.ok(!deepEqual({ a : 1, b : 2 }, undefined));
t.ok(!deepEqual({ a : 1, b : 2 }, {}));
t.ok(!deepEqual(undefined, { a : 1, b : 2 }));
t.ok(!deepEqual({}, { a : 1, b : 2 }));
t.ok(deepEqual(undefined, undefined));
t.ok(deepEqual(null, null));
t.ok(!deepEqual(undefined, null));
t.end();
});
test('deepLevels', function (t) {
var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ];
t.ok(!deepEqual(xs, []));
t.end();
});
var test = require('tape');
var traverse = require('../');
test('traverse an Error', function (t) {
var obj = new Error("test");
var results = traverse(obj).map(function (node) {});
t.same(results, { message: 'test' });
t.end();
});
var test = require('tape');
var traverse = require('../');
test('has', function (t) {
var obj = { a : 2, b : [ 4, 5, { c : 6 } ] };
t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true)
t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false)
t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false)
t.equal(traverse(obj).has([]), true)
t.equal(traverse(obj).has([ 'a' ]), true)
t.equal(traverse(obj).has([ 'a', 2 ]), false)
t.end();
});
var test = require('tape');
var traverse = require('../');
var EventEmitter = require('events').EventEmitter;
test('check instanceof on node elems', function (t) {
var counts = { emitter : 0 };
traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }])
.forEach(function (node) {
if (node instanceof EventEmitter) counts.emitter ++;
})
;
t.equal(counts.emitter, 2);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('interface map', function (t) {
var obj = { a : [ 5,6,7 ], b : { c : [8] } };
t.same(
traverse.paths(obj)
.sort()
.map(function (path) { return path.join('/') })
.slice(1)
.join(' ')
,
'a a/0 a/1 a/2 b b/c b/c/0'
);
t.same(
traverse.nodes(obj),
[
{ a: [ 5, 6, 7 ], b: { c: [ 8 ] } },
[ 5, 6, 7 ], 5, 6, 7,
{ c: [ 8 ] }, [ 8 ], 8
]
);
t.same(
traverse.map(obj, function (node) {
if (typeof node == 'number') {
return node + 1000;
}
else if (Array.isArray(node)) {
return node.join(' ');
}
}),
{ a: '5 6 7', b: { c: '8' } }
);
var nodes = 0;
traverse.forEach(obj, function (node) { nodes ++ });
t.same(nodes, 8);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('json test', function (t) {
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
t.equal(
scrubbed.moo, '[Function]',
'obj.moo replaced with "[Function]"'
);
t.equal(
scrubbed.foo[3], '[Function]',
'obj.foo[3] replaced with "[Function]"'
);
t.same(scrubbed, {
moo : '[Function]',
foo : [ 2, 3, 4, "[Function]" ]
}, 'Full JSON string matches');
t.same(
typeof obj.moo, 'function',
'Original obj.moo still a function'
);
t.same(
typeof obj.foo[3], 'function',
'Original obj.foo[3] still a function'
);
t.same(callbacks, {
54: { id: 54, f : obj.moo, path: [ 'moo' ] },
55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] },
}, 'Check the generated callbacks list');
t.end();
});
var test = require('tape');
var traverse = require('../');
test('sort test', function (t) {
var acc = [];
traverse({
a: 30,
b: 22,
id: 9
}).forEach(function (node) {
if ((! Array.isArray(node)) && typeof node === 'object') {
this.before(function(node) {
this.keys = Object.keys(node);
this.keys.sort(function(a, b) {
a = [a === "id" ? 0 : 1, a];
b = [b === "id" ? 0 : 1, b];
return a < b ? -1 : a > b ? 1 : 0;
});
});
}
if (this.isLeaf) acc.push(node);
});
t.equal(
acc.join(' '),
'9 30 22',
'Traversal in a custom order'
);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('leaves test', function (t) {
var acc = [];
traverse({
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 }
}).forEach(function (x) {
if (this.isLeaf) acc.push(x);
});
t.equal(
acc.join(' '),
'1 2 3 4 5 6 7 8 9',
'Traversal in the right(?) order'
);
t.end();
});
var traverse = require('../../');
module.exports = function (a, b) {
if (arguments.length !== 2) {
throw new Error(
'deepEqual requires exactly two objects to compare against'
);
}
var equal = true;
var node = b;
traverse(a).forEach(function (y) {
var notEqual = (function () {
equal = false;
//this.stop();
return undefined;
}).bind(this);
//if (node === undefined || node === null) return notEqual();
if (!this.isRoot) {
/*
if (!Object.hasOwnProperty.call(node, this.key)) {
return notEqual();
}
*/
if (typeof node !== 'object') return notEqual();
node = node[this.key];
}
var x = node;
this.post(function () {
node = x;
});
var toS = function (o) {
return Object.prototype.toString.call(o);
};
if (this.circular) {
if (traverse(b).get(this.circular.path) !== x) notEqual();
}
else if (typeof x !== typeof y) {
notEqual();
}
else if (x === null || y === null || x === undefined || y === undefined) {
if (x !== y) notEqual();
}
else if (x.__proto__ !== y.__proto__) {
notEqual();
}
else if (x === y) {
// nop
}
else if (typeof x === 'function') {
if (x instanceof RegExp) {
// both regexps on account of the __proto__ check
if (x.toString() != y.toString()) notEqual();
}
else if (x !== y) notEqual();
}
else if (typeof x === 'object') {
if (toS(y) === '[object Arguments]'
|| toS(x) === '[object Arguments]') {
if (toS(x) !== toS(y)) {
notEqual();
}
}
else if (toS(y) === '[object RegExp]'
|| toS(x) === '[object RegExp]') {
if (!x || !y || x.toString() !== y.toString()) notEqual();
}
else if (x instanceof Date || y instanceof Date) {
if (!(x instanceof Date) || !(y instanceof Date)
|| x.getTime() !== y.getTime()) {
notEqual();
}
}
else {
var kx = Object.keys(x);
var ky = Object.keys(y);
if (kx.length !== ky.length) return notEqual();
for (var i = 0; i < kx.length; i++) {
var k = kx[i];
if (!Object.hasOwnProperty.call(y, k)) {
notEqual();
}
}
}
}
});
return equal;
};
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('mutate', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('mutateT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.forEach(obj, function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('map', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('mapT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.map(obj, function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('clone', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).clone();
t.same(obj, res);
t.ok(obj !== res);
obj.a ++;
t.same(res.a, 1);
obj.c.push(5);
t.same(res.c, [ 3, 4 ]);
t.end();
});
test('cloneT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.clone(obj);
t.same(obj, res);
t.ok(obj !== res);
obj.a ++;
t.same(res.a, 1);
obj.c.push(5);
t.same(res.c, [ 3, 4 ]);
t.end();
});
test('reduce', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, [ 1, 2, 3, 4 ]);
t.end();
});
test('reduceInit', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).reduce(function (acc, x) {
if (this.isRoot) assert.fail('got root');
return acc;
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, obj);
t.end();
});
test('remove', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.remove();
});
t.same(obj, { a : 1, c : [ 3 ] });
t.end();
});
exports.removeNoStop = function() {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.remove();
});
t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f'])
t.end();
}
exports.removeStop = function() {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.remove(true);
});
t.same(keys, [undefined, 'a', 'b', 'c', 'f'])
t.end();
}
test('removeMap', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.remove();
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, c : [ 3 ] });
t.end();
});
test('delete', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, undefined ] }
));
t.ok(deepEqual(
obj, { a : 1, c : [ 3 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, null ] }
));
t.end();
});
test('deleteNoStop', function (t) {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.delete();
});
t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e'])
t.end();
});
test('deleteStop', function (t) {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.delete(true);
});
t.same(keys, [undefined, 'a', 'b', 'c'])
t.end();
});
test('deleteRedux', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, undefined, 5 ] }
));
t.ok(deepEqual(
obj, { a : 1, c : [ 3 ,, 5 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, null, 5 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, 5 ] }
));
t.end();
});
test('deleteMap', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(deepEqual(
obj,
{ a : 1, b : 2, c : [ 3, 4 ] }
));
var xs = [ 3, 4 ];
delete xs[1];
t.ok(deepEqual(
res, { a : 1, c : xs }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3, ] }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3 ] }
));
t.end();
});
test('deleteMapRedux', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(deepEqual(
obj,
{ a : 1, b : 2, c : [ 3, 4, 5 ] }
));
var xs = [ 3, 4, 5 ];
delete xs[1];
t.ok(deepEqual(
res, { a : 1, c : xs }
));
t.ok(!deepEqual(
res, { a : 1, c : [ 3, 5 ] }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3 ,, 5 ] }
));
t.end();
});
test('objectToString', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'object' && !this.isRoot) {
this.update(JSON.stringify(x));
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 2, c : "[3,4]" });
t.end();
});
test('stringToObject', function (t) {
var obj = { a : 1, b : 2, c : "[3,4]" };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'string') {
this.update(JSON.parse(x));
}
else if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.deepEqual(obj, res);
t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
var traverse = require('../');
var test = require('tape');
test('negative update test', function (t) {
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var fixed = traverse.map(obj, function (x) {
if (x < 0) this.update(x + 128);
});
t.same(fixed,
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ],
'Negative values += 128'
);
t.same(obj,
[ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ],
'Original references not modified'
);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('traverse an object with nested functions', function (t) {
t.plan(1);
function Cons (x) {
t.equal(x, 10)
};
traverse(new Cons(10));
});
var test = require('tape');
var traverse = require('../');
test('siblings', function (t) {
var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] };
var res = traverse(obj).reduce(function (acc, x) {
var p = '/' + this.path.join('/');
if (this.parent) {
acc[p] = {
siblings : this.parent.keys,
key : this.key,
index : this.parent.keys.indexOf(this.key)
};
}
else {
acc[p] = {
siblings : [],
key : this.key,
index : -1
}
}
return acc;
}, {});
t.same(res, {
'/' : { siblings : [], key : undefined, index : -1 },
'/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 },
'/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 },
'/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 },
'/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 },
'/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 },
'/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 }
});
t.end();
});
var test = require('tape');
var traverse = require('../');
test('stop', function (t) {
var visits = 0;
traverse('abcdefghij'.split('')).forEach(function (node) {
if (typeof node === 'string') {
visits ++;
if (node === 'e') this.stop()
}
});
t.equal(visits, 5);
t.end();
});
test('stopMap', function (t) {
var s = traverse('abcdefghij'.split('')).map(function (node) {
if (typeof node === 'string') {
if (node === 'e') this.stop()
return node.toUpperCase();
}
}).join('');
t.equal(s, 'ABCDEfghij');
t.end();
});
test('stopReduce', function (t) {
var obj = {
a : [ 4, 5 ],
b : [ 6, [ 7, 8, 9 ] ]
};
var xs = traverse(obj).reduce(function (acc, node) {
if (this.isLeaf) {
if (node === 7) this.stop();
else acc.push(node)
}
return acc;
}, []);
t.same(xs, [ 4, 5, 6 ]);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('stringify', function (t) {
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var s = '';
traverse(obj).forEach(function (node) {
if (Array.isArray(node)) {
this.before(function () { s += '[' });
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += ']' });
}
else if (typeof node == 'object') {
this.before(function () { s += '{' });
this.pre(function (x, key) {
s += '"' + key + '"' + ':';
});
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += '}' });
}
else if (typeof node == 'function') {
s += 'null';
}
else {
s += node.toString();
}
});
t.equal(s, JSON.stringify(obj));
t.end();
});
var traverse = require('../');
var test = require('tape');
test('subexpr', function (t) {
var obj = [ 'a', 4, 'b', 5, 'c', 6 ];
var r = traverse(obj).map(function (x) {
if (typeof x === 'number') {
this.update([ x - 0.1, x, x + 0.1 ], true);
}
});
t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]);
t.same(r, [
'a', [ 3.9, 4, 4.1 ],
'b', [ 4.9, 5, 5.1 ],
'c', [ 5.9, 6, 6.1 ],
]);
t.end();
});
test('block', function (t) {
var obj = [ [ 1 ], [ 2 ], [ 3 ] ];
var r = traverse(obj).map(function (x) {
if (Array.isArray(x) && !this.isRoot) {
if (x[0] === 5) this.block()
else this.update([ [ x[0] + 1 ] ])
}
});
t.same(r, [
[ [ [ [ [ 5 ] ] ] ] ],
[ [ [ [ 5 ] ] ] ],
[ [ [ 5 ] ] ],
]);
t.end();
});
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('super_deep', function (t) {
var util = require('util');
var a0 = make();
var a1 = make();
t.ok(deepEqual(a0, a1));
a0.c.d.moo = true;
t.ok(!deepEqual(a0, a1));
a1.c.d.moo = true;
t.ok(deepEqual(a0, a1));
// TODO: this one
//a0.c.a = a1;
//t.ok(!deepEqual(a0, a1));
t.end();
});
function make () {
var a = { self : 'a' };
var b = { self : 'b' };
var c = { self : 'c' };
var d = { self : 'd' };
var e = { self : 'e' };
a.a = a;
a.b = b;
a.c = c;
b.a = a;
b.b = b;
b.c = c;
c.a = a;
c.b = b;
c.c = c;
c.d = d;
d.a = a;
d.b = b;
d.c = c;
d.d = d;
d.e = e;
e.a = a;
e.b = b;
e.c = c;
e.d = d;
e.e = e;
return a;
}
var traverse = require('./');
var test = require('testling');
test('leaves', function (t) {
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 }
};
var acc = [];
traverse(obj).forEach(function (x) {
if (this.isLeaf) acc.push(x);
});
t.deepEqual(
acc, [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
'traversal in the proper order'
);
t.end();
});
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"hashish": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
"integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
"requires": {
"traverse": "0.6.6"
}
},
"lodash": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
"dev": true
},
"traverse": {
"version": "0.6.6",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
}
}
}
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository": {
"type": "git",
"url": "http://github.com/example/example.git"
},
"dependencies": {
"hashish": "*"
},
"engines": {
"node": "8.x"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"heroku-postbuild": "ls node_modules"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
Hashish
=======
Hashish is a node.js library for manipulating hash data structures.
It is distilled from the finest that ruby, perl, and haskell have to offer by
way of hash/map interfaces.
Hashish provides a chaining interface, where you can do:
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
Output:
a => 10
b => 20
Some functions and attributes in the chaining interface are terminal, like
`.items` or `.detect()`. They return values of their own instead of the chain
context.
Each function in the chainable interface is also attached to `Hash` in chainless
form:
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
Output:
{ a: 10, b: 20, c: 30, d: 40 }
In either case, the 'this' context of the function calls is the same object that
the chained functions return, so you can make nested chains.
Methods
=======
forEach(cb)
-----------
For each key/value in the hash, calls `cb(value, key)`.
map(cb)
-------
For each key/value in the hash, calls `cb(value, key)`.
The return value of `cb` is the new value at `key` in the resulting hash.
filter(cb)
----------
For each key/value in the hash, calls `cb(value, key)`.
The resulting hash omits key/value pairs where `cb` returned a falsy value.
detect(cb)
----------
Returns the first value in the hash for which `cb(value, key)` is non-falsy.
Order of hashes is not well-defined so watch out for that.
reduce(cb)
----------
Returns the accumulated value of a left-fold over the key/value pairs.
some(cb)
--------
Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy
value.
update(obj1, [obj2, obj3, ...])
-----------
Mutate the context hash, merging the key/value pairs from the passed objects
and overwriting keys from the context hash if the current `obj` has keys of
the same name. Falsy arguments are silently ignored.
updateAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `update()` but operate on an array directly.
merge(obj1, [obj2, obj3, ...])
----------
Merge the key/value pairs from the passed objects into the resultant hash
without modifying the context hash. Falsy arguments are silently ignored.
mergeAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `merge()` but operate on an array directly.
has(key)
--------
Return whether the hash has a key, `key`.
valuesAt(keys)
--------------
Return an Array with the values at the keys from `keys`.
tap(cb)
-------
Call `cb` with the present raw hash.
This function is chainable.
extract(keys)
-------------
Filter by including only those keys in `keys` in the resulting hash.
exclude(keys)
-------------
Filter by excluding those keys in `keys` in the resulting hash.
Attributes
==========
These are attributes in the chaining interface and functions in the `Hash.xxx`
interface.
keys
----
Return all the enumerable attribute keys in the hash.
values
------
Return all the enumerable attribute values in the hash.
compact
-------
Filter out values which are `=== undefined`.
clone
-----
Make a deep copy of the hash.
copy
----
Make a shallow copy of the hash.
length
------
Return the number of key/value pairs in the hash.
Note: use `Hash.size()` for non-chain mode.
size
----
Alias for `length` since `Hash.length` is masked by `Function.prototype`.
See Also
========
See also [creationix's pattern/hash](http://github.com/creationix/pattern),
which does a similar thing except with hash inputs and array outputs.
Installation
============
To install with [npm](http://github.com/isaacs/npm):
npm install hashish
To run the tests with [expresso](http://github.com/visionmedia/expresso):
expresso
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
module.exports = Hash;
var Traverse = require('traverse');
function Hash (hash, xs) {
if (Array.isArray(hash) && Array.isArray(xs)) {
var to = Math.min(hash.length, xs.length);
var acc = {};
for (var i = 0; i < to; i++) {
acc[hash[i]] = xs[i];
}
return Hash(acc);
}
if (hash === undefined) return Hash({});
var self = {
map : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
acc[key] = f.call(self, hash[key], key);
});
return Hash(acc);
},
forEach : function (f) {
Object.keys(hash).forEach(function (key) {
f.call(self, hash[key], key);
});
return self;
},
filter : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
if (f.call(self, hash[key], key)) {
acc[key] = hash[key];
}
});
return Hash(acc);
},
detect : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) {
return hash[key];
}
}
return undefined;
},
reduce : function (f, acc) {
var keys = Object.keys(hash);
if (acc === undefined) acc = keys.shift();
keys.forEach(function (key) {
acc = f.call(self, acc, hash[key], key);
});
return acc;
},
some : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) return true;
}
return false;
},
update : function (obj) {
if (arguments.length > 1) {
self.updateAll([].slice.call(arguments));
}
else {
Object.keys(obj).forEach(function (key) {
hash[key] = obj[key];
});
}
return self;
},
updateAll : function (xs) {
xs.filter(Boolean).forEach(function (x) {
self.update(x);
});
return self;
},
merge : function (obj) {
if (arguments.length > 1) {
return self.copy.updateAll([].slice.call(arguments));
}
else {
return self.copy.update(obj);
}
},
mergeAll : function (xs) {
return self.copy.updateAll(xs);
},
has : function (key) { // only operates on enumerables
return Array.isArray(key)
? key.every(function (k) { return self.has(k) })
: self.keys.indexOf(key.toString()) >= 0;
},
valuesAt : function (keys) {
return Array.isArray(keys)
? keys.map(function (key) { return hash[key] })
: hash[keys]
;
},
tap : function (f) {
f.call(self, hash);
return self;
},
extract : function (keys) {
var acc = {};
keys.forEach(function (key) {
acc[key] = hash[key];
});
return Hash(acc);
},
exclude : function (keys) {
return self.filter(function (_, key) {
return keys.indexOf(key) < 0
});
},
end : hash,
items : hash
};
var props = {
keys : function () { return Object.keys(hash) },
values : function () {
return Object.keys(hash).map(function (key) { return hash[key] });
},
compact : function () {
return self.filter(function (x) { return x !== undefined });
},
clone : function () { return Hash(Hash.clone(hash)) },
copy : function () { return Hash(Hash.copy(hash)) },
length : function () { return Object.keys(hash).length },
size : function () { return self.length }
};
if (Object.defineProperty) {
// es5-shim has an Object.defineProperty but it throws for getters
try {
for (var key in props) {
Object.defineProperty(self, key, { get : props[key] });
}
}
catch (err) {
for (var key in props) {
if (key !== 'clone' && key !== 'copy' && key !== 'compact') {
// ^ those keys use Hash() so can't call them without
// a stack overflow
self[key] = props[key]();
}
}
}
}
else if (self.__defineGetter__) {
for (var key in props) {
self.__defineGetter__(key, props[key]);
}
}
else {
// non-lazy version for browsers that suck >_<
for (var key in props) {
self[key] = props[key]();
}
}
return self;
};
// deep copy
Hash.clone = function (ref) {
return Traverse.clone(ref);
};
// shallow copy
Hash.copy = function (ref) {
var hash = { __proto__ : ref.__proto__ };
Object.keys(ref).forEach(function (key) {
hash[key] = ref[key];
});
return hash;
};
Hash.map = function (ref, f) {
return Hash(ref).map(f).items;
};
Hash.forEach = function (ref, f) {
Hash(ref).forEach(f);
};
Hash.filter = function (ref, f) {
return Hash(ref).filter(f).items;
};
Hash.detect = function (ref, f) {
return Hash(ref).detect(f);
};
Hash.reduce = function (ref, f, acc) {
return Hash(ref).reduce(f, acc);
};
Hash.some = function (ref, f) {
return Hash(ref).some(f);
};
Hash.update = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.update.apply(hash, args).items;
};
Hash.merge = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.merge.apply(hash, args).items;
};
Hash.has = function (ref, key) {
return Hash(ref).has(key);
};
Hash.valuesAt = function (ref, keys) {
return Hash(ref).valuesAt(keys);
};
Hash.tap = function (ref, f) {
return Hash(ref).tap(f).items;
};
Hash.extract = function (ref, keys) {
return Hash(ref).extract(keys).items;
};
Hash.exclude = function (ref, keys) {
return Hash(ref).exclude(keys).items;
};
Hash.concat = function (xs) {
var hash = Hash({});
xs.forEach(function (x) { hash.update(x) });
return hash.items;
};
Hash.zip = function (xs, ys) {
return Hash(xs, ys).items;
};
// .length is already defined for function prototypes
Hash.size = function (ref) {
return Hash(ref).size;
};
Hash.compact = function (ref) {
return Hash(ref).compact.items;
};
{
"_from": "hashish@*",
"_id": "hashish@0.0.4",
"_inBundle": false,
"_integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
"_location": "/hashish",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "hashish@*",
"name": "hashish",
"escapedName": "hashish",
"rawSpec": "*",
"saveSpec": null,
"fetchSpec": "*"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
"_shasum": "6d60bc6ffaf711b6afd60e426d077988014e6554",
"_spec": "hashish@*",
"_where": "/Users/jmorrell/workspace/heroku-buildpack-nodejs/test/fixtures/dependencies-modules-checked-in-without-devdependencies",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/node-hashish/issues"
},
"bundleDependencies": false,
"dependencies": {
"traverse": ">=0.2.4"
},
"deprecated": false,
"description": "Hash data structure manipulation functions",
"devDependencies": {
"expresso": ">=0.6.0"
},
"engine": [
"node >=0.2.0"
],
"engines": {
"node": "*"
},
"homepage": "https://github.com/substack/node-hashish#readme",
"keywords": [
"hash",
"object",
"convenience",
"manipulation",
"data structure"
],
"license": "MIT/X11",
"main": "./index.js",
"name": "hashish",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/substack/node-hashish.git"
},
"scripts": {
"test": "expresso"
},
"version": "0.0.4"
}
var Hash = require('hashish');
var assert = require('assert');
exports.map = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).map(function (v) { return v + 1 }).items;
var hash = Hash.map(ref, function (v) { return v + 1 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 2, b : 3 });
assert.deepEqual(hash, { a : 2, b : 3 });
};
exports['cloned map'] = function () {
var ref = { foo : [1,2], bar : [4,5] };
var hash = Hash(ref).clone.map(
function (v) { v.unshift(v[0] - 1); return v }
).items;
assert.deepEqual(ref.foo, [1,2]);
assert.deepEqual(ref.bar, [4,5]);
assert.deepEqual(hash.foo, [0,1,2]);
assert.deepEqual(hash.bar, [3,4,5]);
};
exports.forEach = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var xs = [];
Hash(ref).forEach(function (x, i) {
xs.push([ i, x ]);
});
assert.eql(
xs.map(function (x) { return x[0] }).sort(),
[ '1337', 'a', 'b', 'c' ]
);
assert.eql(
xs.map(function (x) { return x[1] }).sort(),
[ 2, 5, 7, 'leet' ]
);
var ys = [];
Hash.forEach(ref, function (x, i) {
ys.push([ i, x ]);
});
assert.eql(xs.sort(), ys.sort());
};
exports.filter_items = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var items = Hash(ref).filter(function (v, k) {
return v > 5 || k > 5
}).items;
var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 });
assert.deepEqual(items, { 1337 : 'leet', c : 7 });
assert.deepEqual(hash, { 1337 : 'leet', c : 7 });
assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' });
assert.equal(Hash(ref).length, 4);
};
exports.detect = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
var gt6hh = hh.detect(function (x) { return x > 6 });
assert.ok(gt6hh == 7 || gt6hh == 8);
var gt6h = Hash.detect(h, function (x) { return x > 6 });
assert.ok(gt6h == 7 || gt6h == 8);
assert.equal(hh.detect(function (x) { return x > 100 }), undefined);
};
exports.reduce = function () {
var ref = { foo : [1,2], bar : [4,5] };
var sum1 = Hash(ref).reduce(function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum1, 4);
var sum2 = Hash.reduce(ref, function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum2, 4);
};
exports.some = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
assert.ok(Hash.some(h, function (x) { return x > 7 }));
assert.ok(Hash.some(h, function (x) { return x < 6 }));
assert.ok(!Hash.some(h, function (x) { return x > 10 }));
assert.ok(!Hash.some(h, function (x) { return x < 0 }));
assert.ok(hh.some(function (x) { return x > 7 }));
assert.ok(hh.some(function (x) { return x < 6 }));
assert.ok(!hh.some(function (x) { return x > 10 }));
assert.ok(!hh.some(function (x) { return x < 0 }));
};
exports.update = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).clone.update({ c : 3, a : 0 }).items;
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 0, b : 2, c : 3 });
var hash = Hash.update(ref, { c : 3, a : 0 });
assert.deepEqual(ref, hash);
assert.deepEqual(hash, { a : 0, b : 2, c : 3 });
var ref2 = {a: 1};
var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.merge = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).merge({ b : 3, c : 3.14 }).items;
var hash = Hash.merge(ref, { b : 3, c : 3.14 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 1, b : 3, c : 3.14 });
assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 });
var ref2 = { a : 1 };
var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.has = function () {
var h = { a : 4, b : 5 };
var hh = Hash(h);
assert.ok(hh.has('a'));
assert.equal(hh.has('c'), false);
assert.ok(hh.has(['a','b']));
assert.equal(hh.has(['a','b','c']), false);
assert.ok(Hash.has(h, 'a'));
assert.equal(Hash.has(h, 'c'), false);
assert.ok(Hash.has(h, ['a','b']));
assert.equal(Hash.has(h, ['a','b','c']), false);
};
exports.valuesAt = function () {
var h = { a : 4, b : 5, c : 6 };
assert.equal(Hash(h).valuesAt('a'), 4);
assert.equal(Hash(h).valuesAt(['a'])[0], 4);
assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]);
assert.equal(Hash.valuesAt(h, 'a'), 4);
assert.deepEqual(Hash.valuesAt(h, ['a']), [4]);
assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]);
};
exports.tap = function () {
var h = { a : 4, b : 5, c : 6 };
var hh = Hash(h);
hh.tap(function (x) {
assert.ok(this === hh)
assert.eql(x, h);
});
Hash.tap(h, function (x) {
assert.eql(
Object.keys(this).sort(),
Object.keys(hh).sort()
);
assert.eql(x, h);
});
};
exports.extract = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.extract(['a','b']);
assert.equal(extracted.length, 2);
assert.deepEqual(extracted.items, { a : 1, b : 2 });
};
exports.exclude = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.exclude(['a','b']);
assert.equal(extracted.length, 1);
assert.deepEqual(extracted.items, { c : 3 });
};
exports.concat = function () {
var ref1 = { a : 1, b : 2 };
var ref2 = { foo : 100, bar : 200 };
var ref3 = { b : 3, c : 4, bar : 300 };
assert.deepEqual(
Hash.concat([ ref1, ref2 ]),
{ a : 1, b : 2, foo : 100, bar : 200 }
);
assert.deepEqual(
Hash.concat([ ref1, ref2, ref3 ]),
{ a : 1, b : 3, c : 4, foo : 100, bar : 300 }
);
};
exports.zip = function () {
var xs = ['a','b','c'];
var ys = [1,2,3,4];
var h = Hash(xs,ys);
assert.equal(h.length, 3);
assert.deepEqual(h.items, { a : 1, b : 2, c : 3 });
var zipped = Hash.zip(xs,ys);
assert.deepEqual(zipped, { a : 1, b : 2, c : 3 });
};
exports.length = function () {
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3);
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3);
assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3);
};
exports.compact = function () {
var hash = {
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
};
var compacted = Hash(hash).compact;
assert.deepEqual(
{
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
},
hash, 'compact modified the hash'
);
assert.deepEqual(
compacted.items,
{
a : 1,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
}
);
var h = Hash.compact(hash);
assert.deepEqual(h, compacted.items);
};
var Hash = require('hashish');
var assert = require('assert');
var vm = require('vm');
var fs = require('fs');
var src = fs.readFileSync(__dirname + '/../index.js', 'utf8');
exports.defineGetter = function () {
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : undefined,
},
require : require,
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
var times = 0;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
times ++;
return Object.__defineGetter__.apply(this, arguments);
};
assert.equal(vm.runInNewContext('Object.defineProperty', context), null);
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.ok(times > 5);
};
exports.defineProperty = function () {
var times = 0;
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : function (prop) {
times ++;
if (prop.get) throw new TypeError('engine does not support')
assert.fail('should have asserted by now');
},
},
require : require
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
assert.fail('getter called when a perfectly good'
+ ' defineProperty was available'
);
};
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.equal(times, 1);
};
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
http://www.opensource.org/licenses/mit-license.php
Copyright 2010 James Halliday (mail@substack.net)
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.
var traverse = require('traverse');
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
console.dir(scrubbed);
console.dir(callbacks);
var traverse = require('traverse');
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 },
};
var leaves = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
console.dir(leaves);
var traverse = require('traverse');
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
console.dir(obj);
// scrub out circular references
var traverse = require('traverse');
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
obj.c.push(obj);
var scrubbed = traverse(obj).map(function (x) {
if (this.circular) this.remove()
});
console.dir(scrubbed);
#!/usr/bin/env node
var traverse = require('traverse');
var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var s = '';
traverse(obj).forEach(function to_s (node) {
if (Array.isArray(node)) {
this.before(function () { s += '[' });
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += ']' });
}
else if (typeof node == 'object') {
this.before(function () { s += '{' });
this.pre(function (x, key) {
to_s(key);
s += ':';
});
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += '}' });
}
else if (typeof node == 'string') {
s += '"' + node.toString().replace(/"/g, '\\"') + '"';
}
else if (typeof node == 'function') {
s += 'null';
}
else {
s += node.toString();
}
});
console.log('JSON.stringify: ' + JSON.stringify(obj));
console.log('this stringify: ' + s);
var traverse = module.exports = function (obj) {
return new Traverse(obj);
};
function Traverse (obj) {
this.value = obj;
}
Traverse.prototype.get = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
node = undefined;
break;
}
node = node[key];
}
return node;
};
Traverse.prototype.has = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
return false;
}
node = node[key];
}
return true;
};
Traverse.prototype.set = function (ps, value) {
var node = this.value;
for (var i = 0; i < ps.length - 1; i ++) {
var key = ps[i];
if (!hasOwnProperty.call(node, key)) node[key] = {};
node = node[key];
}
node[ps[i]] = value;
return value;
};
Traverse.prototype.map = function (cb) {
return walk(this.value, cb, true);
};
Traverse.prototype.forEach = function (cb) {
this.value = walk(this.value, cb, false);
return this.value;
};
Traverse.prototype.reduce = function (cb, init) {
var skip = arguments.length === 1;
var acc = skip ? this.value : init;
this.forEach(function (x) {
if (!this.isRoot || !skip) {
acc = cb.call(this, acc, x);
}
});
return acc;
};
Traverse.prototype.paths = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.path);
});
return acc;
};
Traverse.prototype.nodes = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.node);
});
return acc;
};
Traverse.prototype.clone = function () {
var parents = [], nodes = [];
return (function clone (src) {
for (var i = 0; i < parents.length; i++) {
if (parents[i] === src) {
return nodes[i];
}
}
if (typeof src === 'object' && src !== null) {
var dst = copy(src);
parents.push(src);
nodes.push(dst);
forEach(objectKeys(src), function (key) {
dst[key] = clone(src[key]);
});
parents.pop();
nodes.pop();
return dst;
}
else {
return src;
}
})(this.value);
};
function walk (root, cb, immutable) {
var path = [];
var parents = [];
var alive = true;
return (function walker (node_) {
var node = immutable ? copy(node_) : node_;
var modifiers = {};
var keepGoing = true;
var state = {
node : node,
node_ : node_,
path : [].concat(path),
parent : parents[parents.length - 1],
parents : parents,
key : path.slice(-1)[0],
isRoot : path.length === 0,
level : path.length,
circular : null,
update : function (x, stopHere) {
if (!state.isRoot) {
state.parent.node[state.key] = x;
}
state.node = x;
if (stopHere) keepGoing = false;
},
'delete' : function (stopHere) {
delete state.parent.node[state.key];
if (stopHere) keepGoing = false;
},
remove : function (stopHere) {
if (isArray(state.parent.node)) {
state.parent.node.splice(state.key, 1);
}
else {
delete state.parent.node[state.key];
}
if (stopHere) keepGoing = false;
},
keys : null,
before : function (f) { modifiers.before = f },
after : function (f) { modifiers.after = f },
pre : function (f) { modifiers.pre = f },
post : function (f) { modifiers.post = f },
stop : function () { alive = false },
block : function () { keepGoing = false }
};
if (!alive) return state;
function updateState() {
if (typeof state.node === 'object' && state.node !== null) {
if (!state.keys || state.node_ !== state.node) {
state.keys = objectKeys(state.node)
}
state.isLeaf = state.keys.length == 0;
for (var i = 0; i < parents.length; i++) {
if (parents[i].node_ === node_) {
state.circular = parents[i];
break;
}
}
}
else {
state.isLeaf = true;
state.keys = null;
}
state.notLeaf = !state.isLeaf;
state.notRoot = !state.isRoot;
}
updateState();
// use return values to update if defined
var ret = cb.call(state, state.node);
if (ret !== undefined && state.update) state.update(ret);
if (modifiers.before) modifiers.before.call(state, state.node);
if (!keepGoing) return state;
if (typeof state.node == 'object'
&& state.node !== null && !state.circular) {
parents.push(state);
updateState();
forEach(state.keys, function (key, i) {
path.push(key);
if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
var child = walker(state.node[key]);
if (immutable && hasOwnProperty.call(state.node, key)) {
state.node[key] = child.node;
}
child.isLast = i == state.keys.length - 1;
child.isFirst = i == 0;
if (modifiers.post) modifiers.post.call(state, child);
path.pop();
});
parents.pop();
}
if (modifiers.after) modifiers.after.call(state, state.node);
return state;
})(root).node;
}
function copy (src) {
if (typeof src === 'object' && src !== null) {
var dst;
if (isArray(src)) {
dst = [];
}
else if (isDate(src)) {
dst = new Date(src.getTime ? src.getTime() : src);
}
else if (isRegExp(src)) {
dst = new RegExp(src);
}
else if (isError(src)) {
dst = { message: src.message };
}
else if (isBoolean(src)) {
dst = new Boolean(src);
}
else if (isNumber(src)) {
dst = new Number(src);
}
else if (isString(src)) {
dst = new String(src);
}
else if (Object.create && Object.getPrototypeOf) {
dst = Object.create(Object.getPrototypeOf(src));
}
else if (src.constructor === Object) {
dst = {};
}
else {
var proto =
(src.constructor && src.constructor.prototype)
|| src.__proto__
|| {}
;
var T = function () {};
T.prototype = proto;
dst = new T;
}
forEach(objectKeys(src), function (key) {
dst[key] = src[key];
});
return dst;
}
else return src;
}
var objectKeys = Object.keys || function keys (obj) {
var res = [];
for (var key in obj) res.push(key)
return res;
};
function toS (obj) { return Object.prototype.toString.call(obj) }
function isDate (obj) { return toS(obj) === '[object Date]' }
function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
function isError (obj) { return toS(obj) === '[object Error]' }
function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
function isNumber (obj) { return toS(obj) === '[object Number]' }
function isString (obj) { return toS(obj) === '[object String]' }
var isArray = Array.isArray || function isArray (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
var forEach = function (xs, fn) {
if (xs.forEach) return xs.forEach(fn)
else for (var i = 0; i < xs.length; i++) {
fn(xs[i], i, xs);
}
};
forEach(objectKeys(Traverse.prototype), function (key) {
traverse[key] = function (obj) {
var args = [].slice.call(arguments, 1);
var t = new Traverse(obj);
return t[key].apply(t, args);
};
});
var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
return key in obj;
};
{
"_from": "traverse@>=0.2.4",
"_id": "traverse@0.6.6",
"_inBundle": false,
"_integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
"_location": "/traverse",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "traverse@>=0.2.4",
"name": "traverse",
"escapedName": "traverse",
"rawSpec": ">=0.2.4",
"saveSpec": null,
"fetchSpec": ">=0.2.4"
},
"_requiredBy": [
"/hashish"
],
"_resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
"_shasum": "cbdf560fd7b9af632502fed40f918c157ea97137",
"_spec": "traverse@>=0.2.4",
"_where": "/Users/jmorrell/workspace/heroku-buildpack-nodejs/test/fixtures/dependencies-modules-checked-in-without-devdependencies/node_modules/hashish",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/js-traverse/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "traverse and transform objects by visiting every node on a recursive walk",
"devDependencies": {
"tape": "~1.0.4"
},
"directories": {
"example": "example",
"test": "test"
},
"homepage": "https://github.com/substack/js-traverse",
"keywords": [
"traverse",
"walk",
"recursive",
"map",
"forEach",
"deep",
"clone"
],
"license": "MIT",
"main": "index.js",
"name": "traverse",
"repository": {
"type": "git",
"url": "git://github.com/substack/js-traverse.git"
},
"scripts": {
"test": "tape test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": {
"iexplore": [
"6.0",
"7.0",
"8.0",
"9.0"
],
"chrome": [
"10.0",
"20.0"
],
"firefox": [
"10.0",
"15.0"
],
"safari": [
"5.1"
],
"opera": [
"12.0"
]
}
},
"version": "0.6.6"
}
# traverse
Traverse and transform objects by visiting every node on a recursive walk.
[![browser support](http://ci.testling.com/substack/js-traverse.png)](http://ci.testling.com/substack/js-traverse)
[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse)
# examples
## transform negative numbers in-place
negative.js
````javascript
var traverse = require('traverse');
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
console.dir(obj);
````
Output:
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
## collect leaf nodes
leaves.js
````javascript
var traverse = require('traverse');
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 },
};
var leaves = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
console.dir(leaves);
````
Output:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
## scrub circular references
scrub.js:
````javascript
var traverse = require('traverse');
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
obj.c.push(obj);
var scrubbed = traverse(obj).map(function (x) {
if (this.circular) this.remove()
});
console.dir(scrubbed);
````
output:
{ a: 1, b: 2, c: [ 3, 4 ] }
# methods
Each method that takes an `fn` uses the context documented below in the context
section.
## .map(fn)
Execute `fn` for each node in the object and return a new object with the
results of the walk. To update nodes in the result use `this.update(value)`.
## .forEach(fn)
Execute `fn` for each node in the object but unlike `.map()`, when
`this.update()` is called it updates the object in-place.
## .reduce(fn, acc)
For each node in the object, perform a
[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))
with the return value of `fn(acc, node)`.
If `acc` isn't specified, `acc` is set to the root object for the first step
and the root element is skipped.
## .paths()
Return an `Array` of every possible non-cyclic path in the object.
Paths are `Array`s of string keys.
## .nodes()
Return an `Array` of every node in the object.
## .clone()
Create a deep clone of the object.
## .get(path)
Get the element at the array `path`.
## .set(path, value)
Set the element at the array `path` to `value`.
## .has(path)
Return whether the element at the array `path` exists.
# context
Each method that takes a callback has a context (its `this` object) with these
attributes:
## this.node
The present node on the recursive walk
## this.path
An array of string keys from the root to the present node
## this.parent
The context of the node's parent.
This is `undefined` for the root node.
## this.key
The name of the key of the present node in its parent.
This is `undefined` for the root node.
## this.isRoot, this.notRoot
Whether the present node is the root node
## this.isLeaf, this.notLeaf
Whether or not the present node is a leaf node (has no children)
## this.level
Depth of the node within the traversal
## this.circular
If the node equals one of its parents, the `circular` attribute is set to the
context of that parent and the traversal progresses no deeper.
## this.update(value, stopHere=false)
Set a new value for the present node.
All the elements in `value` will be recursively traversed unless `stopHere` is
true.
## this.remove(stopHere=false)
Remove the current element from the output. If the node is in an Array it will
be spliced off. Otherwise it will be deleted from its parent.
## this.delete(stopHere=false)
Delete the current element from its parent in the output. Calls `delete` even on
Arrays.
## this.before(fn)
Call this function before any of the children are traversed.
You can assign into `this.keys` here to traverse in a custom order.
## this.after(fn)
Call this function after any of the children are traversed.
## this.pre(fn)
Call this function before each of the children are traversed.
## this.post(fn)
Call this function after each of the children are traversed.
# install
Using [npm](http://npmjs.org) do:
$ npm install traverse
# license
MIT
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
var util = require('util');
test('circular', function (t) {
t.plan(1);
var obj = { x : 3 };
obj.y = obj;
traverse(obj).forEach(function (x) {
if (this.path.join('') == 'y') {
t.equal(
util.inspect(this.circular.node),
util.inspect(obj)
);
}
});
});
test('deepCirc', function (t) {
t.plan(2);
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
var times = 0;
traverse(obj).forEach(function (x) {
if (this.circular) {
t.same(this.circular.path, []);
t.same(this.path, [ 'y', 2 ]);
}
});
});
test('doubleCirc', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var circs = [];
traverse(obj).forEach(function (x) {
if (this.circular) {
circs.push({ circ : this.circular, self : this, node : x });
}
});
t.same(circs[0].self.path, [ 'x', 3, 2 ]);
t.same(circs[0].circ.path, []);
t.same(circs[1].self.path, [ 'y', 2 ]);
t.same(circs[1].circ.path, []);
t.same(circs.length, 2);
t.end();
});
test('circDubForEach', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
traverse(obj).forEach(function (x) {
if (this.circular) this.update('...');
});
t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
t.end();
});
test('circDubMap', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var c = traverse(obj).map(function (x) {
if (this.circular) {
this.update('...');
}
});
t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
t.end();
});
test('circClone', function (t) {
var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
obj.y[2] = obj;
obj.x.push(obj.y);
var clone = traverse.clone(obj);
t.ok(obj !== clone);
t.ok(clone.y[2] === clone);
t.ok(clone.y[2] !== obj);
t.ok(clone.x[3][2] === clone);
t.ok(clone.x[3][2] !== obj);
t.same(clone.x.slice(0,3), [1,2,3]);
t.same(clone.y.slice(0,2), [4,5]);
t.end();
});
test('circMapScrub', function (t) {
var obj = { a : 1, b : 2 };
obj.c = obj;
var scrubbed = traverse(obj).map(function (node) {
if (this.circular) this.remove();
});
t.same(
Object.keys(scrubbed).sort(),
[ 'a', 'b' ]
);
t.ok(deepEqual(scrubbed, { a : 1, b : 2 }));
t.equal(obj.c, obj);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('dateEach', function (t) {
var obj = { x : new Date, y : 10, z : 5 };
var counts = {};
traverse(obj).forEach(function (node) {
var t = (node instanceof Date && 'Date') || typeof node;
counts[t] = (counts[t] || 0) + 1;
});
t.same(counts, {
object : 1,
Date : 1,
number : 2,
});
t.end();
});
test('dateMap', function (t) {
var obj = { x : new Date, y : 10, z : 5 };
var res = traverse(obj).map(function (node) {
if (typeof node === 'number') this.update(node + 100);
});
t.ok(obj.x !== res.x);
t.same(res, {
x : obj.x,
y : 110,
z : 105,
});
t.end();
});
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('deepDates', function (t) {
t.plan(2);
t.ok(
deepEqual(
{ d : new Date, x : [ 1, 2, 3 ] },
{ d : new Date, x : [ 1, 2, 3 ] }
),
'dates should be equal'
);
var d0 = new Date;
setTimeout(function () {
t.ok(
!deepEqual(
{ d : d0, x : [ 1, 2, 3 ], },
{ d : new Date, x : [ 1, 2, 3 ] }
),
'microseconds should count in date equality'
);
}, 5);
});
test('deepCircular', function (t) {
var a = [1];
a.push(a); // a = [ 1, *a ]
var b = [1];
b.push(a); // b = [ 1, [ 1, *a ] ]
t.ok(
!deepEqual(a, b),
'circular ref mount points count towards equality'
);
var c = [1];
c.push(c); // c = [ 1, *c ]
t.ok(
deepEqual(a, c),
'circular refs are structurally the same here'
);
var d = [1];
d.push(a); // c = [ 1, [ 1, *d ] ]
t.ok(
deepEqual(b, d),
'non-root circular ref structural comparison'
);
t.end();
});
test('deepInstances', function (t) {
t.ok(
!deepEqual([ new Boolean(false) ], [ false ]),
'boolean instances are not real booleans'
);
t.ok(
!deepEqual([ new String('x') ], [ 'x' ]),
'string instances are not real strings'
);
t.ok(
!deepEqual([ new Number(4) ], [ 4 ]),
'number instances are not real numbers'
);
t.ok(
deepEqual([ new RegExp('x') ], [ /x/ ]),
'regexp instances are real regexps'
);
t.ok(
!deepEqual([ new RegExp(/./) ], [ /../ ]),
'these regexps aren\'t the same'
);
t.ok(
!deepEqual(
[ function (x) { return x * 2 } ],
[ function (x) { return x * 2 } ]
),
'functions with the same .toString() aren\'t necessarily the same'
);
var f = function (x) { return x * 2 };
t.ok(
deepEqual([ f ], [ f ]),
'these functions are actually equal'
);
t.end();
});
test('deepEqual', function (t) {
t.ok(
!deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }),
'arrays are not objects'
);
t.end();
});
test('falsy', function (t) {
t.ok(
!deepEqual([ undefined ], [ null ]),
'null is not undefined!'
);
t.ok(
!deepEqual([ null ], [ undefined ]),
'undefined is not null!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'undefined is not null, however deeply!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'null is not undefined, however deeply!'
);
t.ok(
!deepEqual(
{ a : 1, b : 2, c : [ 3, undefined, 5 ] },
{ a : 1, b : 2, c : [ 3, null, 5 ] }
),
'null is not undefined, however deeply!'
);
t.end();
});
test('deletedArrayEqual', function (t) {
var xs = [ 1, 2, 3, 4 ];
delete xs[2];
var ys = Object.create(Array.prototype);
ys[0] = 1;
ys[1] = 2;
ys[3] = 4;
t.ok(
deepEqual(xs, ys),
'arrays with deleted elements are only equal to'
+ ' arrays with similarly deleted elements'
);
t.ok(
!deepEqual(xs, [ 1, 2, undefined, 4 ]),
'deleted array elements cannot be undefined'
);
t.ok(
!deepEqual(xs, [ 1, 2, null, 4 ]),
'deleted array elements cannot be null'
);
t.end();
});
test('deletedObjectEqual', function (t) {
var obj = { a : 1, b : 2, c : 3 };
delete obj.c;
t.ok(
deepEqual(obj, { a : 1, b : 2 }),
'deleted object elements should not show up'
);
t.ok(
!deepEqual(obj, { a : 1, b : 2, c : undefined }),
'deleted object elements are not undefined'
);
t.ok(
!deepEqual(obj, { a : 1, b : 2, c : null }),
'deleted object elements are not null'
);
t.end();
});
test('emptyKeyEqual', function (t) {
t.ok(!deepEqual(
{ a : 1 }, { a : 1, '' : 55 }
));
t.end();
});
test('deepArguments', function (t) {
t.ok(
!deepEqual(
[ 4, 5, 6 ],
(function () { return arguments })(4, 5, 6)
),
'arguments are not arrays'
);
t.ok(
deepEqual(
(function () { return arguments })(4, 5, 6),
(function () { return arguments })(4, 5, 6)
),
'arguments should equal'
);
t.end();
});
test('deepUn', function (t) {
t.ok(!deepEqual({ a : 1, b : 2 }, undefined));
t.ok(!deepEqual({ a : 1, b : 2 }, {}));
t.ok(!deepEqual(undefined, { a : 1, b : 2 }));
t.ok(!deepEqual({}, { a : 1, b : 2 }));
t.ok(deepEqual(undefined, undefined));
t.ok(deepEqual(null, null));
t.ok(!deepEqual(undefined, null));
t.end();
});
test('deepLevels', function (t) {
var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ];
t.ok(!deepEqual(xs, []));
t.end();
});
var test = require('tape');
var traverse = require('../');
test('traverse an Error', function (t) {
var obj = new Error("test");
var results = traverse(obj).map(function (node) {});
t.same(results, { message: 'test' });
t.end();
});
var test = require('tape');
var traverse = require('../');
test('has', function (t) {
var obj = { a : 2, b : [ 4, 5, { c : 6 } ] };
t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true)
t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false)
t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false)
t.equal(traverse(obj).has([]), true)
t.equal(traverse(obj).has([ 'a' ]), true)
t.equal(traverse(obj).has([ 'a', 2 ]), false)
t.end();
});
var test = require('tape');
var traverse = require('../');
var EventEmitter = require('events').EventEmitter;
test('check instanceof on node elems', function (t) {
var counts = { emitter : 0 };
traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }])
.forEach(function (node) {
if (node instanceof EventEmitter) counts.emitter ++;
})
;
t.equal(counts.emitter, 2);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('interface map', function (t) {
var obj = { a : [ 5,6,7 ], b : { c : [8] } };
t.same(
traverse.paths(obj)
.sort()
.map(function (path) { return path.join('/') })
.slice(1)
.join(' ')
,
'a a/0 a/1 a/2 b b/c b/c/0'
);
t.same(
traverse.nodes(obj),
[
{ a: [ 5, 6, 7 ], b: { c: [ 8 ] } },
[ 5, 6, 7 ], 5, 6, 7,
{ c: [ 8 ] }, [ 8 ], 8
]
);
t.same(
traverse.map(obj, function (node) {
if (typeof node == 'number') {
return node + 1000;
}
else if (Array.isArray(node)) {
return node.join(' ');
}
}),
{ a: '5 6 7', b: { c: '8' } }
);
var nodes = 0;
traverse.forEach(obj, function (node) { nodes ++ });
t.same(nodes, 8);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('json test', function (t) {
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
t.equal(
scrubbed.moo, '[Function]',
'obj.moo replaced with "[Function]"'
);
t.equal(
scrubbed.foo[3], '[Function]',
'obj.foo[3] replaced with "[Function]"'
);
t.same(scrubbed, {
moo : '[Function]',
foo : [ 2, 3, 4, "[Function]" ]
}, 'Full JSON string matches');
t.same(
typeof obj.moo, 'function',
'Original obj.moo still a function'
);
t.same(
typeof obj.foo[3], 'function',
'Original obj.foo[3] still a function'
);
t.same(callbacks, {
54: { id: 54, f : obj.moo, path: [ 'moo' ] },
55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] },
}, 'Check the generated callbacks list');
t.end();
});
var test = require('tape');
var traverse = require('../');
test('sort test', function (t) {
var acc = [];
traverse({
a: 30,
b: 22,
id: 9
}).forEach(function (node) {
if ((! Array.isArray(node)) && typeof node === 'object') {
this.before(function(node) {
this.keys = Object.keys(node);
this.keys.sort(function(a, b) {
a = [a === "id" ? 0 : 1, a];
b = [b === "id" ? 0 : 1, b];
return a < b ? -1 : a > b ? 1 : 0;
});
});
}
if (this.isLeaf) acc.push(node);
});
t.equal(
acc.join(' '),
'9 30 22',
'Traversal in a custom order'
);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('leaves test', function (t) {
var acc = [];
traverse({
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 }
}).forEach(function (x) {
if (this.isLeaf) acc.push(x);
});
t.equal(
acc.join(' '),
'1 2 3 4 5 6 7 8 9',
'Traversal in the right(?) order'
);
t.end();
});
var traverse = require('../../');
module.exports = function (a, b) {
if (arguments.length !== 2) {
throw new Error(
'deepEqual requires exactly two objects to compare against'
);
}
var equal = true;
var node = b;
traverse(a).forEach(function (y) {
var notEqual = (function () {
equal = false;
//this.stop();
return undefined;
}).bind(this);
//if (node === undefined || node === null) return notEqual();
if (!this.isRoot) {
/*
if (!Object.hasOwnProperty.call(node, this.key)) {
return notEqual();
}
*/
if (typeof node !== 'object') return notEqual();
node = node[this.key];
}
var x = node;
this.post(function () {
node = x;
});
var toS = function (o) {
return Object.prototype.toString.call(o);
};
if (this.circular) {
if (traverse(b).get(this.circular.path) !== x) notEqual();
}
else if (typeof x !== typeof y) {
notEqual();
}
else if (x === null || y === null || x === undefined || y === undefined) {
if (x !== y) notEqual();
}
else if (x.__proto__ !== y.__proto__) {
notEqual();
}
else if (x === y) {
// nop
}
else if (typeof x === 'function') {
if (x instanceof RegExp) {
// both regexps on account of the __proto__ check
if (x.toString() != y.toString()) notEqual();
}
else if (x !== y) notEqual();
}
else if (typeof x === 'object') {
if (toS(y) === '[object Arguments]'
|| toS(x) === '[object Arguments]') {
if (toS(x) !== toS(y)) {
notEqual();
}
}
else if (toS(y) === '[object RegExp]'
|| toS(x) === '[object RegExp]') {
if (!x || !y || x.toString() !== y.toString()) notEqual();
}
else if (x instanceof Date || y instanceof Date) {
if (!(x instanceof Date) || !(y instanceof Date)
|| x.getTime() !== y.getTime()) {
notEqual();
}
}
else {
var kx = Object.keys(x);
var ky = Object.keys(y);
if (kx.length !== ky.length) return notEqual();
for (var i = 0; i < kx.length; i++) {
var k = kx[i];
if (!Object.hasOwnProperty.call(y, k)) {
notEqual();
}
}
}
}
});
return equal;
};
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('mutate', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('mutateT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.forEach(obj, function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('map', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('mapT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.map(obj, function (x) {
if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
test('clone', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).clone();
t.same(obj, res);
t.ok(obj !== res);
obj.a ++;
t.same(res.a, 1);
obj.c.push(5);
t.same(res.c, [ 3, 4 ]);
t.end();
});
test('cloneT', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse.clone(obj);
t.same(obj, res);
t.ok(obj !== res);
obj.a ++;
t.same(res.a, 1);
obj.c.push(5);
t.same(res.c, [ 3, 4 ]);
t.end();
});
test('reduce', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, [ 1, 2, 3, 4 ]);
t.end();
});
test('reduceInit', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).reduce(function (acc, x) {
if (this.isRoot) assert.fail('got root');
return acc;
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, obj);
t.end();
});
test('remove', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.remove();
});
t.same(obj, { a : 1, c : [ 3 ] });
t.end();
});
exports.removeNoStop = function() {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.remove();
});
t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f'])
t.end();
}
exports.removeStop = function() {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.remove(true);
});
t.same(keys, [undefined, 'a', 'b', 'c', 'f'])
t.end();
}
test('removeMap', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.remove();
});
t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
t.same(res, { a : 1, c : [ 3 ] });
t.end();
});
test('delete', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, undefined ] }
));
t.ok(deepEqual(
obj, { a : 1, c : [ 3 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, null ] }
));
t.end();
});
test('deleteNoStop', function (t) {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.delete();
});
t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e'])
t.end();
});
test('deleteStop', function (t) {
var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
var keys = [];
traverse(obj).forEach(function (x) {
keys.push(this.key)
if (this.key == 'c') this.delete(true);
});
t.same(keys, [undefined, 'a', 'b', 'c'])
t.end();
});
test('deleteRedux', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
traverse(obj).forEach(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, undefined, 5 ] }
));
t.ok(deepEqual(
obj, { a : 1, c : [ 3 ,, 5 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, null, 5 ] }
));
t.ok(!deepEqual(
obj, { a : 1, c : [ 3, 5 ] }
));
t.end();
});
test('deleteMap', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(deepEqual(
obj,
{ a : 1, b : 2, c : [ 3, 4 ] }
));
var xs = [ 3, 4 ];
delete xs[1];
t.ok(deepEqual(
res, { a : 1, c : xs }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3, ] }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3 ] }
));
t.end();
});
test('deleteMapRedux', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
var res = traverse(obj).map(function (x) {
if (this.isLeaf && x % 2 == 0) this.delete();
});
t.ok(deepEqual(
obj,
{ a : 1, b : 2, c : [ 3, 4, 5 ] }
));
var xs = [ 3, 4, 5 ];
delete xs[1];
t.ok(deepEqual(
res, { a : 1, c : xs }
));
t.ok(!deepEqual(
res, { a : 1, c : [ 3, 5 ] }
));
t.ok(deepEqual(
res, { a : 1, c : [ 3 ,, 5 ] }
));
t.end();
});
test('objectToString', function (t) {
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'object' && !this.isRoot) {
this.update(JSON.stringify(x));
}
});
t.same(obj, res);
t.same(obj, { a : 1, b : 2, c : "[3,4]" });
t.end();
});
test('stringToObject', function (t) {
var obj = { a : 1, b : 2, c : "[3,4]" };
var res = traverse(obj).forEach(function (x) {
if (typeof x === 'string') {
this.update(JSON.parse(x));
}
else if (typeof x === 'number' && x % 2 === 0) {
this.update(x * 10);
}
});
t.deepEqual(obj, res);
t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] });
t.end();
});
var traverse = require('../');
var test = require('tape');
test('negative update test', function (t) {
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var fixed = traverse.map(obj, function (x) {
if (x < 0) this.update(x + 128);
});
t.same(fixed,
[ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ],
'Negative values += 128'
);
t.same(obj,
[ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ],
'Original references not modified'
);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('traverse an object with nested functions', function (t) {
t.plan(1);
function Cons (x) {
t.equal(x, 10)
};
traverse(new Cons(10));
});
var test = require('tape');
var traverse = require('../');
test('siblings', function (t) {
var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] };
var res = traverse(obj).reduce(function (acc, x) {
var p = '/' + this.path.join('/');
if (this.parent) {
acc[p] = {
siblings : this.parent.keys,
key : this.key,
index : this.parent.keys.indexOf(this.key)
};
}
else {
acc[p] = {
siblings : [],
key : this.key,
index : -1
}
}
return acc;
}, {});
t.same(res, {
'/' : { siblings : [], key : undefined, index : -1 },
'/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 },
'/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 },
'/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 },
'/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 },
'/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 },
'/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 }
});
t.end();
});
var test = require('tape');
var traverse = require('../');
test('stop', function (t) {
var visits = 0;
traverse('abcdefghij'.split('')).forEach(function (node) {
if (typeof node === 'string') {
visits ++;
if (node === 'e') this.stop()
}
});
t.equal(visits, 5);
t.end();
});
test('stopMap', function (t) {
var s = traverse('abcdefghij'.split('')).map(function (node) {
if (typeof node === 'string') {
if (node === 'e') this.stop()
return node.toUpperCase();
}
}).join('');
t.equal(s, 'ABCDEfghij');
t.end();
});
test('stopReduce', function (t) {
var obj = {
a : [ 4, 5 ],
b : [ 6, [ 7, 8, 9 ] ]
};
var xs = traverse(obj).reduce(function (acc, node) {
if (this.isLeaf) {
if (node === 7) this.stop();
else acc.push(node)
}
return acc;
}, []);
t.same(xs, [ 4, 5, 6 ]);
t.end();
});
var test = require('tape');
var traverse = require('../');
test('stringify', function (t) {
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var s = '';
traverse(obj).forEach(function (node) {
if (Array.isArray(node)) {
this.before(function () { s += '[' });
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += ']' });
}
else if (typeof node == 'object') {
this.before(function () { s += '{' });
this.pre(function (x, key) {
s += '"' + key + '"' + ':';
});
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += '}' });
}
else if (typeof node == 'function') {
s += 'null';
}
else {
s += node.toString();
}
});
t.equal(s, JSON.stringify(obj));
t.end();
});
var traverse = require('../');
var test = require('tape');
test('subexpr', function (t) {
var obj = [ 'a', 4, 'b', 5, 'c', 6 ];
var r = traverse(obj).map(function (x) {
if (typeof x === 'number') {
this.update([ x - 0.1, x, x + 0.1 ], true);
}
});
t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]);
t.same(r, [
'a', [ 3.9, 4, 4.1 ],
'b', [ 4.9, 5, 5.1 ],
'c', [ 5.9, 6, 6.1 ],
]);
t.end();
});
test('block', function (t) {
var obj = [ [ 1 ], [ 2 ], [ 3 ] ];
var r = traverse(obj).map(function (x) {
if (Array.isArray(x) && !this.isRoot) {
if (x[0] === 5) this.block()
else this.update([ [ x[0] + 1 ] ])
}
});
t.same(r, [
[ [ [ [ [ 5 ] ] ] ] ],
[ [ [ [ 5 ] ] ] ],
[ [ [ 5 ] ] ],
]);
t.end();
});
var test = require('tape');
var traverse = require('../');
var deepEqual = require('./lib/deep_equal');
test('super_deep', function (t) {
var util = require('util');
var a0 = make();
var a1 = make();
t.ok(deepEqual(a0, a1));
a0.c.d.moo = true;
t.ok(!deepEqual(a0, a1));
a1.c.d.moo = true;
t.ok(deepEqual(a0, a1));
// TODO: this one
//a0.c.a = a1;
//t.ok(!deepEqual(a0, a1));
t.end();
});
function make () {
var a = { self : 'a' };
var b = { self : 'b' };
var c = { self : 'c' };
var d = { self : 'd' };
var e = { self : 'e' };
a.a = a;
a.b = b;
a.c = c;
b.a = a;
b.b = b;
b.c = c;
c.a = a;
c.b = b;
c.c = c;
c.d = d;
d.a = a;
d.b = b;
d.c = c;
d.d = d;
d.e = e;
e.a = a;
e.b = b;
e.c = c;
e.d = d;
e.e = e;
return a;
}
var traverse = require('./');
var test = require('testling');
test('leaves', function (t) {
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 }
};
var acc = [];
traverse(obj).forEach(function (x) {
if (this.isLeaf) acc.push(x);
});
t.deepEqual(
acc, [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
'traversal in the proper order'
);
t.end();
});
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"hashish": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
"integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
"requires": {
"traverse": "0.6.6"
}
},
"traverse": {
"version": "0.6.6",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
}
}
}
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository": {
"type": "git",
"url": "http://github.com/example/example.git"
},
"dependencies": {
"hashish": "*"
},
"engines": {
"node": "8.x"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"heroku-postbuild": "ls node_modules"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository": {
"type": "git",
"url": "http://github.com/example/example.git"
},
"dependencies": {
"hashish": "*"
},
"license": "MIT",
"engines": {
"yarn": "1.4.0"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"heroku-postbuild": "ls node_modules"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
hashish@*:
version "0.0.4"
resolved "https://registry.yarnpkg.com/hashish/-/hashish-0.0.4.tgz#6d60bc6ffaf711b6afd60e426d077988014e6554"
dependencies:
traverse ">=0.2.4"
lodash@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e"
traverse@>=0.2.4:
version "0.6.6"
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository": {
"type": "git",
"url": "http://github.com/example/example.git"
},
"dependencies": {
"hashish": "*"
},
"engines": {
"node": "8.x"
},
"devDependencies": {
"lodash": "^2.4.1"
},
"scripts": {
"heroku-postbuild": "ls node_modules"
}
}
{
"name": "yarn",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"lodash": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
}
}
}
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"engines": {
"npm": "5.5.1"
},
"scripts": {
"heroku-prebuild": "echo 'heroku-prebuild:' $NODE_ENV",
"preinstall": "echo 'preinstall:' $NODE_ENV",
"postinstall": "echo 'postinstall:' $NODE_ENV",
"heroku-postbuild": "echo 'heroku-postbuild:' $NODE_ENV"
},
"devDependencies": {
"mocha": "*"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
{
"name": "yarn",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"lodash": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
}
}
}
{
"name": "missing-devdeps-1",
"name": "yarn",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"postinstall": "node postinstall.js"
"license": "MIT",
"engines": {
"npm": "5.3.0"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"lodash": "4.13.1"
"mocha": "*"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
......@@ -8,5 +8,8 @@
},
"dependencies": {
"lodash": "^4.16.4"
},
"devDependencies": {
"mocha": "^5.0.1"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
browser-stdout@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
commander@2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"
diff@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
escape-string-regexp@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
glob@7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
growl@1.10.3:
version "1.10.3"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f"
has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
he@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
dependencies:
once "^1.3.0"
wrappy "1"
inherits@2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
mkdirp@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
mocha@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.1.tgz#759b62c836b0732382a62b6b1fb245ec1bc943ac"
dependencies:
browser-stdout "1.3.0"
commander "2.11.0"
debug "3.1.0"
diff "3.3.1"
escape-string-regexp "1.0.5"
glob "7.1.2"
growl "1.10.3"
he "1.1.1"
mkdirp "0.5.1"
supports-color "4.4.0"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
once@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
supports-color@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"
dependencies:
has-flag "^2.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
{
"name": "yarn",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"engines": {
"yarn": "1.x"
},
"dependencies": {
"lodash": "^4.16.4"
}
}
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
lodash:
version "4.16.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127"
......@@ -125,13 +125,20 @@ testOldYarn() {
compile "yarn-old-deprecated-version"
assertCaptured "Resolving yarn version ~0.16"
assertCaptured "installing yarn (0.16."
assertCaptured "error: unknown option \`--frozen-lockfile'"
assertCaptured "error \`install\` has been replaced with \`add\`"
assertCaptured "Outdated Yarn version"
assertCaptured "Your application is specifying a requirement on an old version of Yarn"
assertCaptured "https://devcenter.heroku.com/articles/nodejs-support#specifying-a-yarn-version"
assertCapturedError
}
testYarnV1Semver() {
compile "yarn-v1-semver"
assertCaptured "Downloading and installing yarn (1."
assertCaptured "Installed yarn 1."
assertCapturedSuccess
}
testYarnInvalid() {
compile "yarn-invalid"
assertCaptured "Resolving yarn version 0.171"
......@@ -263,10 +270,6 @@ testWarnDevDeps() {
assertCaptured "A module may be missing"
assertNotCaptured "This module may be specified"
assertCapturedError
compile "missing-devdeps-2"
assertCaptured "A module may be missing"
assertCaptured "This module may be specified"
assertCapturedError
compile "failing-build"
assertNotCaptured "A module may be missing"
assertNotCaptured "This module may be specified"
......@@ -641,13 +644,6 @@ testEnvVars() {
assertCapturedSuccess
}
testNoEnvVars() {
env_dir=$(mktmpdir)
compile "stable-node" "$(mktmpdir)" $env_dir
assertCaptured "NPM_CONFIG_PRODUCTION=true"
assertCapturedSuccess
}
testNonFileEnvVars() {
export NPM_CONFIG_FOO=bar
export NPM_CONFIG_PRODUCTION=false
......@@ -659,17 +655,99 @@ testNonFileEnvVars() {
unset NPM_CONFIG_PRODUCTION
}
testNoDevDependencies() {
compile "dev-dependencies"
assertNotCaptured "lodash"
# In the following tests "lodash" is defined as a devDependency
# testing for lodash is equivalent to testing if devDependencies
# were installed
# Default behavior: install devDependencies then prunes them away
testDevDependenciesInstalled() {
compile "dependencies"
assertCaptured "lodash"
assertCaptured "Pruning devDependencies"
assertCaptured "removed 1 package"
assertCapturedSuccess
}
testDevDependencies() {
# Default behavior: install devDependencies then prunes them away with Yarn
testDevDependenciesInstalledYarn() {
compile "dependencies-yarn"
assertCaptured "lodash"
assertCaptured "Pruning devDependencies"
assertCapturedSuccess
}
# When NPM_CONFIG_PRODUCTION = false we should not prune the devDependencies
testDevDepenenciesWithNoPruning() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
compile "dev-dependencies" "$(mktmpdir)" $env_dir
compile "dependencies" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCaptured "Skipping because NPM_CONFIG_PRODUCTION is not 'true'"
assertCapturedSuccess
}
# When NPM_CONFIG_PRODUCTION = false we should not prune the devDependencies with Yarn
testDevDepenenciesWithNoPruningYarn() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/YARN_PRODUCTION
compile "dependencies-yarn" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCaptured "Skipping because YARN_PRODUCTION is not 'true'"
assertCapturedSuccess
}
# When NODE_ENV != production we should not prune the devDependencies
testNodeEnvTestDepenencies() {
env_dir=$(mktmpdir)
echo "not-production" > $env_dir/NODE_ENV
compile "dependencies" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCaptured "Skipping because NODE_ENV is not 'production'"
assertCapturedSuccess
}
# When NODE_ENV != production we should not prune the devDependencies with Yarn
testNodeEnvTestDepenenciesYarn() {
env_dir=$(mktmpdir)
echo "not-production" > $env_dir/NODE_ENV
compile "dependencies-yarn" "$(mktmpdir)" $env_dir
assertCaptured "lodash"
assertCaptured "Skipping because NODE_ENV is not 'production'"
assertCapturedSuccess
}
# When NPM_CONFIG_PRODUCTION = true we should not install devDependencies
testOnlyDependenciesInstalled() {
env_dir=$(mktmpdir)
echo "true" > $env_dir/NPM_CONFIG_PRODUCTION
compile "dependencies" "$(mktmpdir)" $env_dir
assertNotCaptured "lodash"
assertCapturedSuccess
}
# When NPM_CONFIG_PRODUCTION = true we should not install devDependencies with Yarn
testOnlyDependenciesInstalledYarn() {
env_dir=$(mktmpdir)
echo "true" > $env_dir/YARN_PRODUCTION
compile "dependencies-yarn" "$(mktmpdir)" $env_dir
assertNotCaptured "lodash"
assertCapturedSuccess
}
testModulesCheckedInWithDevDependencies() {
compile "dependencies-modules-checked-in-with-devdependencies"
assertCaptured "Rebuilding any native modules"
assertCaptured "lodash"
assertCaptured "removed 1 package"
assertCapturedSuccess
}
testModulesCheckedInWithoutDevDependencies() {
compile "dependencies-modules-checked-in-without-devdependencies"
assertCaptured "Rebuilding any native modules"
assertCaptured "added 1 package"
assertCaptured "lodash"
assertCaptured "removed 1 package"
assertCapturedSuccess
}
......@@ -699,10 +777,6 @@ testNoOptionalDependencies() {
}
testNpmrc() {
compile "dev-dependencies"
assertNotCaptured "lodash"
assertCapturedSuccess
compile "dev-dependencies-npmrc"
assertCaptured "lodash"
assertCapturedSuccess
......@@ -712,7 +786,7 @@ testShrinkwrap() {
compile "shrinkwrap"
assertCaptured "express@4.10.4"
assertCaptured "lodash@2.4.0"
assertNotCaptured "mocha"
assertCaptured "mocha@2.0.1"
assertCapturedSuccess
}
......@@ -751,6 +825,48 @@ testCIEnvVarsOverride() {
assertCapturedSuccess
}
testCIDependencies() {
compileTest "ci-dependencies"
assertCaptured "lodash"
assertCapturedSuccess
}
testCIDependenciesYarn() {
compileTest "ci-dependencies-yarn"
assertCaptured "lodash"
assertCapturedSuccess
}
testNodeEnv() {
compile "node-env-consistency"
assertCaptured "heroku-prebuild: production"
assertCaptured "preinstall: production"
assertCaptured "postinstall: production"
assertCaptured "heroku-postbuild: production"
assertCapturedSuccess
}
testNodeEnvNpmConfigProductionFalse() {
env_dir=$(mktmpdir)
echo "false" > $env_dir/NPM_CONFIG_PRODUCTION
compile "node-env-consistency" "$(mktmpdir)" $env_dir
assertCaptured "heroku-prebuild: production"
assertCaptured "preinstall: production"
assertCaptured "postinstall: production"
assertCaptured "heroku-postbuild: production"
assertCapturedSuccess
}
# Avoid this issue
# https://github.com/npm/npm/issues/17781
testNpmPrune53Issue() {
compile "npm-prune-5-3-issue"
assertCaptured "npm 5.3.0 installed"
assertCaptured "Skipping because npm 5.3.0 fails"
assertCaptured "https://github.com/npm/npm/issues/17781"
assertCapturedSuccess
}
# Utils
pushd $(dirname 0) >/dev/null
......@@ -811,6 +927,10 @@ compileTest() {
for f in ${compile_dir}/.profile.d/*; do source $f > /dev/null 2> /dev/null ; done
capture ${bp_dir}/bin/test ${compile_dir}
unset HOME
unset NODE_ENV
unset NODE_HOME
}
compileDir() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment