Compare commits

..

2 Commits

Author SHA1 Message Date
jdalton
f2d87df120 Bump to v3.10.0. 2015-06-30 09:40:56 -07:00
jdalton
7351c0b0b9 Rebuild lodash and docs. 2015-06-29 23:19:08 -07:00
90 changed files with 39930 additions and 72727 deletions

View File

@@ -4,9 +4,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
[**.{js,json,md}]
indent_style = space
indent_size = 2
insert_final_newline = true
[**.html]
indent_style = tab
insert_final_newline = false

View File

@@ -1,78 +0,0 @@
# Contributing to Lodash
Contributions are always welcome. Before contributing please read the
[code of conduct](https://js.foundation/conduct/) &
[search the issue tracker](https://github.com/lodash/lodash/issues); your issue
may have already been discussed or fixed in `master`. To contribute,
[fork](https://help.github.com/articles/fork-a-repo/) Lodash, commit your changes,
& [send a pull request](https://help.github.com/articles/using-pull-requests/).
## Feature Requests
Feature requests should be submitted in the
[issue tracker](https://github.com/lodash/lodash/issues), with a description of
the expected behavior & use case, where theyll remain closed until sufficient interest,
[e.g. :+1: reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/),
has been [shown by the community](https://github.com/lodash/lodash/issues?q=label%3A%22votes+needed%22+sort%3Areactions-%2B1-desc).
Before submitting a request, please search for similar ones in the
[closed issues](https://github.com/lodash/lodash/issues?q=is%3Aissue+is%3Aclosed+label%3Aenhancement).
## Pull Requests
For additions or bug fixes you should only need to modify `lodash.js`. Include
updated unit tests in the `test` directory as part of your pull request. Dont
worry about regenerating the `dist/` or `doc/` files.
Before running the unit tests youll need to install, `npm i`,
[development dependencies](https://docs.npmjs.com/files/package.json#devdependencies).
Run unit tests from the command-line via `npm test`, or open `test/index.html` &
`test/fp.html` in a web browser. The [Backbone](http://backbonejs.org/) &
[Underscore](http://underscorejs.org/) test suites are included as well.
## Contributor License Agreement
Lodash is a member of the [JS Foundation](https://js.foundation/).
As such, we request that all contributors sign the JS Foundation
[contributor license agreement (CLA)](https://js.foundation/CLA/).
For more information about CLAs, please check out Alex Russells excellent post,
[“Why Do I Need to Sign This?”](https://infrequently.org/2008/06/why-do-i-need-to-sign-this/).
## Coding Guidelines
In addition to the following guidelines, please follow the conventions already
established in the code.
- **Spacing**:<br>
Use two spaces for indentation. No tabs.
- **Naming**:<br>
Keep variable & method names concise & descriptive.<br>
Variable names `index`, `array`, & `iteratee` are preferable to
`i`, `arr`, & `fn`.
- **Quotes**:<br>
Single-quoted strings are preferred to double-quoted strings; however,
please use a double-quoted string if the value contains a single-quote
character to avoid unnecessary escaping.
- **Comments**:<br>
Please use single-line comments to annotate significant additions, &
[JSDoc-style](http://www.2ality.com/2011/08/jsdoc-intro.html) comments for
functions.
Guidelines are enforced using [JSCS](https://www.npmjs.com/package/jscs):
```bash
$ npm run style
```
## Tips
You can opt-in to a pre-push git hook by adding an `.opt-in` file to the root of
the project containing:
```txt
pre-push
```
With that, when you `git push`, the pre-push git hook will trigger and execute
`npm run validate`.

4
.gitignore vendored
View File

@@ -1,4 +1,6 @@
.DS_Store
*.custom.*
*.log
doc/*.html
*.map
lodash.compat.min.js
node_modules

97
.jscsrc
View File

@@ -1,97 +0,0 @@
{
"maxErrors": "2000",
"maximumLineLength": {
"value": 180,
"allExcept": ["comments", "functionSignature", "regex"]
},
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch"
],
"requireOperatorBeforeLineBreak": [
"=",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!==",
">",
">=",
"<",
"<="
],
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"return",
"try",
"catch"
],
"requireSpaceBeforeBinaryOperators": [
"=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
"&=", "|=", "^=",
"+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
"|", "^", "&&", "||", "===", "==", ">=",
"<=", "<", ">", "!=", "!=="
],
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"requireCamelCaseOrUpperCaseIdentifiers": true,
"requireDotNotation": { "allExcept": ["keywords"] },
"requireEarlyReturn": true,
"requireLineFeedAtFileEnd": true,
"requireSemicolons": true,
"requireSpaceAfterBinaryOperators": true,
"requireSpacesInConditionalExpression": true,
"requireSpaceBeforeObjectValues": true,
"requireSpaceBeforeBlockStatements": true,
"requireSpacesInForStatement": true,
"validateIndentation": 2,
"validateParameterSeparator": ", ",
"validateQuoteMarks": { "mark": "'", "escape": true },
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowKeywords": ["with"],
"disallowMixedSpacesAndTabs": true,
"disallowMultipleLineBreaks": true,
"disallowNewlineBeforeBlockStatements": true,
"disallowSpaceAfterObjectKeys": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowSpacesInCallExpression": true,
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideParentheses": true,
"disallowTrailingWhitespace": true,
"disallowUnusedVariables": true,
"jsDoc": {
"checkRedundantAccess": true,
"checkTypes": true,
"requireNewlineAfterDescription": true,
"requireParamDescription": true,
"requireParamTypes": true,
"requireReturnTypes": true
}
}

View File

@@ -1,11 +0,0 @@
'use strict';
delete global['__core-js_shared__'];
const _ = require('./lodash.js');
const globals = require('lodash-doc-globals');
module.exports = {
'babel': false,
'globals': _.assign({ '_': _ }, globals)
};

View File

@@ -1,135 +1,76 @@
language: node_js
sudo: false
node_js:
- 7
addons:
jwt:
secure: OYhRpW+8A0Iik+9GmHwa45ZwXeBXw/6zh6I+1w2H9g/LqPRp+Nhq3f4FSpvrrfno8lO8W4h+7s6+JOzF8C8NxNda5UUygKjF9pUphgiQdqls3YZMJlC9zXVl7gQXAHi3nG1s8vWSpwpzYD9fqczE1FX9n0+R63qX3eB6C/LbPeI=
cache:
directories:
- ~/.npm
- ~/.yarn-cache
- travis_phantomjs
- "0.12"
env:
global:
- BIN=node ISTANBUL=false OPTION=""
- SAUCE_LABS=false SAUCE_USERNAME=lodash
- PATTERN1="s|\s*else\s*\{\s*iteratee\(index\);\s*\}||"
- BIN="node" BUILD="compat" ISTANBUL=false OPTION=""
- NPM_VERSION="^2.0.0" SAUCE_LABS=false SAUCE_USERNAME="lodash"
- secure: "tg1JFsIFnxzLaTboFPOnm+aJCuMm5+JdhLlESlqg9x3fwro++7KCnwHKLNovhchaPe4otC43ZMB/nfWhDnDm11dKbm/V6HlTkED+dadTsaLxVDg6J+7yK41QhokBPJOxLV78iDaNaAQVYEirAgZ0yn8kFubxmNKV+bpCGQNc9yU="
matrix:
-
- BIN=phantomjs
- ISTANBUL=true
- SAUCE_LABS=true
- BUILD="compat"
- BUILD="modern"
- BUILD="modern"
- BUILD="modern" ISTANBUL=true
- BIN="phantomjs"
- BIN="rhino" OPTION="-opt -1"
- BIN="rhino" OPTION="-opt -1 -require"
- BIN="ringo" OPTION="-o -1"
matrix:
include:
- node_js: 6
- node_js: "iojs"
env:
- node_js: "iojs"
env: BUILD="modern"
- node_js: "0.8"
env: NPM_VERSION="~1.4.0"
- node_js: "0.8"
env: BUILD="modern" NPM_VERSION="~1.4.0"
- node_js: "0.10"
env:
- node_js: "0.10"
env: BUILD="modern"
- node_js: "0.12"
env: SAUCE_LABS=true
- node_js: "0.12"
env: SAUCE_LABS=true BUILD="modern"
git:
depth: 10
branches:
only:
- master
- 4.17.5
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/4aab6358b0e9aed0b628
on_success: change
on_failure: always
before_install:
# Upgrade PhantomJS.
- |
export PHANTOMJS_VERSION=2.1.1
export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH
if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then
rm -rf $PWD/travis_phantomjs
mkdir -p $PWD/travis_phantomjs
wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2
tar -xvf phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs
fi
phantomjs -v
# Use exact Node version.
- nvm use $TRAVIS_NODE_VERSION
# Setup package managers.
- npm set loglevel error
- npm set progress false
- npm i -g yarn@0.16.1
- yarn -V
# Remove code skipped on the coverage run.
- |
PATTERN[0]="|\s*while\s*\([^)]+\)\s*\{\s*iteratee\(index\);\s*\}|"
PATTERN[1]="|\bindex,\s*iterable\)\s*===\s*false\)[^}]+?(break;)|"
PATTERN[2]="|\bcase\s+(?:dataView|promise|set|map|weakMap)CtorString:.+|g"
PATTERN[3]="|\s*if\s*\(cache\.size\b[\s\S]+?\}|"
PATTERN[4]="|\s*if\s*\(\!lodashFunc\)\s*\{\s*return;\s*\}|"
PATTERN[5]="|\s*define\([\s\S]+?\);|"
PATTERN[6]="|\s*root\._\s*=\s*_;|"
if [ $ISTANBUL = true ]; then
set -e
for PTRN in ${PATTERN[@]}; do
node ./test/remove.js $PTRN ./lodash.js
done
fi
install:
# Install packages.
- yarn
# Use lodash-cli from GitHub.
- git clone --depth=10 --branch=master git://github.com/lodash/lodash-cli ./node_modules/lodash-cli
- mkdir -p ./node_modules/lodash-cli/node_modules/lodash; cd $_; cp ../../../../lodash.js ./lodash.js; cp ../../../../package.json ./package.json
- cd ../../; npm i --production; cd ../../
- "nvm use $TRAVIS_NODE_VERSION"
- "npm config set loglevel error"
- "npm i -g npm@\"$NPM_VERSION\""
- "[ $SAUCE_LABS == false ] || npm i chalk@\"^1.0.0\" ecstatic@\"0.8.0\" request@\"^2.0.0\" sauce-tunnel@\"2.2.3\""
- "[ $ISTANBUL == false ] || (npm i -g coveralls@\"^2.0.0\" && npm i istanbul@\"0.3.17\")"
- "[ $BIN != 'rhino' ] || (sudo mkdir /opt/rhino-1.7.6 && sudo wget --no-check-certificate -O $_/js.jar https://lodash.com/_travis/rhino-1.7.6.jar)"
- "[ $BIN != 'rhino' ] || (echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7.6/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino)"
- "[ $BIN != 'ringo' ] || (wget --no-check-certificate https://lodash.com/_travis/ringojs-0.11.zip && sudo unzip ringojs-0.11 -d /opt && rm ringojs-0.11.zip)"
- "[ $BIN != 'ringo' ] || (sudo ln -s /opt/ringojs-0.11/bin/ringo /usr/local/bin/ringo && sudo chmod +x $_)"
- "perl -pi -e 's|\"lodash\"|\"lodash-compat\"|' ./package.json"
- "git clone --depth=10 --branch=master git://github.com/lodash/lodash-cli ./node_modules/lodash-cli && mkdir $_/node_modules && cd $_ && ln -s ../../../ ./lodash-compat && cd ../ && npm i && cd ../../"
- "node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./lodash.$BUILD.js"
script:
# Detect code coverage.
- |
if [ $ISTANBUL = true ]; then
istanbul cover -x "**/vendor/**" --report lcovonly ./test/test.js -- ./lodash.js
if [ $TRAVIS_SECURE_ENV_VARS = true ]; then
cat ./coverage/lcov.info | coveralls
cat ./coverage/coverage.json | codecov
fi
fi
# Test in Node.js and PhantomJS.
- |
if [ $ISTANBUL = false ]; then
node ./node_modules/lodash-cli/bin/lodash -o ./dist/lodash.js
node ./node_modules/lodash-cli/bin/lodash modularize exports=node -o ./
node ./node_modules/lodash-cli/bin/lodash -d -o ./lodash.js
if [ $SAUCE_LABS = false ]; then
cd ./test
$BIN $OPTION ./test.js ../lodash.js
if [ $TRAVIS_SECURE_ENV_VARS = true ]; then
$BIN $OPTION ./test.js ../dist/lodash.min.js
fi
fi
fi
# Test in Sauce Labs.
- |
if [ $SAUCE_LABS = true ]; then
node ./node_modules/lodash-cli/bin/lodash core -o ./dist/lodash.core.js
npm run build
$BIN ./test/saucelabs.js name="lodash tests" runner="test/index.html?build=../dist/lodash.js&noglobals=true" tags=development
$BIN ./test/saucelabs.js name="lodash tests" runner="test/index.html?build=../dist/lodash.min.js&noglobals=true" tags=production
$BIN ./test/saucelabs.js name="lodash-fp tests" runner="test/fp.html?noglobals=true" tags=development
$BIN ./test/saucelabs.js name="underscore tests" runner="test/underscore.html?build=../dist/lodash.js" tags=development,underscore
$BIN ./test/saucelabs.js name="underscore tests" runner="test/underscore.html?build=../dist/lodash.min.js" tags=production,underscore
$BIN ./test/saucelabs.js name="backbone tests" runner="test/backbone.html?build=../dist/lodash.js" tags=development,backbone
$BIN ./test/saucelabs.js name="backbone tests" runner="test/backbone.html?build=../dist/lodash.min.js" tags=production,backbone
$BIN ./test/saucelabs.js name="backbone tests" runner="test/backbone.html?build=../dist/lodash.core.js" tags=development,backbone
$BIN ./test/saucelabs.js name="backbone tests" runner="test/backbone.html?build=../dist/lodash.core.min.js" tags=production,backbone
fi
- "[ $ISTANBUL == false ] || cp ./lodash.$BUILD.js ./lodash.js"
- "[ $ISTANBUL == false ] || perl -0pi -e \"$PATTERN\" ./lodash.js"
- "[ $ISTANBUL == false ] || node ./node_modules/istanbul/lib/cli.js cover -x \"**/vendor/**\" --report lcovonly ./test/test.js -- ./lodash.js"
- "[ $ISTANBUL == false ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || (cat ./coverage/lcov.info | coveralls) || true"
- "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || cd ./test"
- "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || $BIN $OPTION ./test.js ../lodash.$BUILD.js"
- "[ $SAUCE_LABS == true ] || [ $ISTANBUL == true ] || [ $TRAVIS_SECURE_ENV_VARS == false ] || $BIN $OPTION ./test.js ../lodash.$BUILD.min.js"
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.$BUILD.js&noglobals=true\" tags=\"$BUILD,development\""
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.$BUILD.min.js&noglobals=true\" tags=\"$BUILD,production\""
- "[ $SAUCE_LABS == false ] || [ $BUILD != 'compat' ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.$BUILD.js\" tags=\"$BUILD,development,ie-compat\" compatMode=7"
- "[ $SAUCE_LABS == false ] || [ $BUILD != 'compat' ] || $BIN ./test/saucelabs.js name=\"lodash tests\" runner=\"test/index.html?build=../lodash.$BUILD.min.js\" tags=\"$BUILD,production,ie-compat\" compatMode=7"
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"backbone tests\" runner=\"test/backbone.html?build=../lodash.$BUILD.min.js\" tags=\"$BUILD,production,backbone\""
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"backbone tests\" runner=\"test/backbone.html?build=../lodash.$BUILD.js\" tags=\"$BUILD,development,backbone\""
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"underscore tests\" runner=\"test/underscore.html?build=../lodash.$BUILD.min.js\" tags=\"$BUILD,production,underscore\""
- "[ $SAUCE_LABS == false ] || $BIN ./test/saucelabs.js name=\"underscore tests\" runner=\"test/underscore.html?build=../lodash.$BUILD.js\" tags=\"$BUILD,development,underscore\""

View File

@@ -1 +0,0 @@
https://github.com/lodash/lodash/wiki/Changelog

39
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,39 @@
# Contributing to lodash
If youd like to contribute a feature or bug fix, you can [fork](https://help.github.com/articles/fork-a-repo/) lodash, commit your changes, & [send a pull request](https://help.github.com/articles/using-pull-requests/).
Please make sure to [search the issue tracker](https://github.com/lodash/lodash/issues) first; your issue may have already been discussed or fixed in `master`.
## Tests
Include updated unit tests in the `test` directory as part of your pull request.
Dont worry about regenerating the documentation, lodash.js, or lodash.min.js.
Before running the unit tests youll need to install, `npm i`, [development dependencies](https://docs.npmjs.com/files/package.json#devdependencies).
Run unit tests from the command-line via `node test/test`, or open `test/index.html` in a web browser.
The `test/run-test.sh` script attempts to run the tests in [Rhino](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino), [RingoJS](http://ringojs.org/), [PhantomJS](http://phantomjs.org/), & [Node](http://nodejs.org/), before running them in your default browser.
The [Backbone](http://backbonejs.org/) & [Underscore](http://underscorejs.org/) test suites are included as well.
## Contributor License Agreement
lodash is a member of the [Dojo Foundation](http://dojofoundation.org/).
As such, we request that all contributors sign the Dojo Foundation [contributor license agreement](http://dojofoundation.org/about/claForm).
For more information about CLAs, please check out Alex Russells excellent post, [“Why Do I Need to Sign This?”](http://infrequently.org/2008/06/why-do-i-need-to-sign-this/).
## Coding Guidelines
In addition to the following guidelines, please follow the conventions already established in the code.
- **Spacing**:<br>
Use two spaces for indentation. No tabs.
- **Naming**:<br>
Keep variable & method names concise & descriptive.<br>
Variable names `index`, `collection`, & `callback` are preferable to `i`, `arr`, & `fn`.
- **Quotes**:<br>
Single-quoted strings are preferred to double-quoted strings; however, please use a double-quoted string if the value contains a single-quote character to avoid unnecessary escaping.
- **Comments**:<br>
Please use single-line comments to annotate significant additions, & [JSDoc-style](http://www.2ality.com/2011/08/jsdoc-intro.html) comments for new methods.

29
LICENSE
View File

@@ -1,17 +1,7 @@
Copyright JS Foundation and other contributors <https://js.foundation/>
Based on Underscore.js, copyright Jeremy Ashkenas,
Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js, copyright 2009-2015 Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash
The following license applies to all parts of this software except as
documented below:
====
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
@@ -30,18 +20,3 @@ 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.
====
Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.
CC0: http://creativecommons.org/publicdomain/zero/1.0/
====
Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.

View File

@@ -1,80 +1,29 @@
# lodash v4.17.5
# lodash v3.10.0
[Site](https://lodash.com/) |
[Docs](https://lodash.com/docs) |
[FP Guide](https://github.com/lodash/lodash/wiki/FP-Guide) |
[Contributing](https://github.com/lodash/lodash/blob/master/.github/CONTRIBUTING.md) |
[Wiki](https://github.com/lodash/lodash/wiki "Changelog, Roadmap, etc.") |
[Code of Conduct](https://js.foundation/conduct/) |
[Twitter](https://twitter.com/bestiejs) |
[Chat](https://gitter.im/lodash/lodash)
The [Lodash](https://lodash.com/) library exported as a [UMD](https://github.com/umdjs/umd) module.
The [modern build](https://github.com/lodash/lodash/wiki/Build-Differences) of [lodash](https://lodash.com/) with packages for [Bower](http://bower.io/), [Component](http://component.github.io/), & [Volo](http://volojs.org/).
Generated using [lodash-cli](https://www.npmjs.com/package/lodash-cli):
```shell
$ npm run build
$ lodash -o ./dist/lodash.js
$ lodash core -o ./dist/lodash.core.js
```bash
$ lodash modern -o ./lodash.js
```
## Download
## Community
* [Core build](https://raw.githubusercontent.com/lodash/lodash/4.17.5/dist/lodash.core.js) ([~4 kB gzipped](https://raw.githubusercontent.com/lodash/lodash/4.17.5/dist/lodash.core.min.js))
* [Full build](https://raw.githubusercontent.com/lodash/lodash/4.17.5/dist/lodash.js) ([~24 kB gzipped](https://raw.githubusercontent.com/lodash/lodash/4.17.5/dist/lodash.min.js))
* [CDN copies](https://www.jsdelivr.com/projects/lodash)
[![Join the chat at https://gitter.im/lodash/lodash](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lodash/lodash)
Lodash is released under the [MIT license](https://raw.githubusercontent.com/lodash/lodash/4.17.5/LICENSE) & supports modern environments.<br>
Review the [build differences](https://github.com/lodash/lodash/wiki/build-differences) & pick one thats right for you.
## Module formats
## Installation
lodash is also available in a variety of other builds & module formats.
In a browser:
```html
<script src="lodash.js"></script>
```
* npm packages for [modern](https://www.npmjs.com/package/lodash), [compatibility](https://www.npmjs.com/package/lodash-compat), & [per method](https://www.npmjs.com/browse/keyword/lodash-modularized) builds
* AMD modules for [modern](https://github.com/lodash/lodash/tree/3.10.0-amd) & [compatibility](https://github.com/lodash/lodash-compat/tree/3.10.0-amd) builds
* ES modules for the [modern](https://github.com/lodash/lodash/tree/3.10.0-es) build
Using npm:
```shell
$ npm i -g npm
$ npm i --save lodash
```
## Further Reading
In Node.js:
```js
// Load the full build.
var _ = require('lodash');
// Load the core build.
var _ = require('lodash/core');
// Load the FP build for immutable auto-curried iteratee-first data-last methods.
var fp = require('lodash/fp');
// Load method categories.
var array = require('lodash/array');
var object = require('lodash/fp/object');
// Cherry-pick methods for smaller browserify/rollup/webpack bundles.
var at = require('lodash/at');
var curryN = require('lodash/fp/curryN');
```
**Note:**<br>
Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL.
## Why Lodash?
Lodash makes JavaScript easier by taking the hassle out of working with arrays,<br>
numbers, objects, strings, etc. Lodashs modular methods are great for:
* Iterating arrays, objects, & strings
* Manipulating & testing values
* Creating composite functions
## Module Formats
Lodash is available in a [variety of builds](https://lodash.com/custom-builds) & module formats.
* [lodash](https://www.npmjs.com/package/lodash) & [per method packages](https://www.npmjs.com/browse/keyword/lodash-modularized)
* [lodash-es](https://www.npmjs.com/package/lodash-es), [babel-plugin-lodash](https://www.npmjs.com/package/babel-plugin-lodash), & [lodash-webpack-plugin](https://www.npmjs.com/package/lodash-webpack-plugin)
* [lodash/fp](https://github.com/lodash/lodash/tree/npm/fp)
* [lodash-amd](https://www.npmjs.com/package/lodash-amd)
* [API Documentation](https://lodash.com/docs)
* [Build Differences](https://github.com/lodash/lodash/wiki/Build-Differences)
* [Changelog](https://github.com/lodash/lodash/wiki/Changelog)
* [Release Notes](https://github.com/lodash/lodash/releases)
* [Roadmap](https://github.com/lodash/lodash/wiki/Roadmap)
* [More Resources](https://github.com/lodash/lodash/wiki/Resources)

19
bower.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "lodash",
"main": "lodash.js",
"ignore": [
".*",
"*.custom.*",
"*.log",
"*.map",
"*.md",
"lodash.src.js",
"component.json",
"package.json",
"doc",
"node_modules",
"perf",
"test",
"vendor"
]
}

10
component.json Normal file
View File

@@ -0,0 +1,10 @@
{
"name": "lodash",
"repo": "lodash/lodash",
"version": "3.10.0",
"description": "The modern build of lodash.",
"license": "MIT",
"main": "lodash.js",
"keywords": ["stdlib", "util"],
"scripts": ["lodash.js"]
}

3854
dist/lodash.core.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
/**
* @license
* Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
* Build: `lodash core -o ./dist/lodash.core.js`
*/
;(function(){function n(n){return H(n)&&pn.call(n,"callee")&&!yn.call(n,"callee")}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return j(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");
return setTimeout(function(){n.apply(Z,r)},t)}function f(n,t){var r=true;return mn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function a(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function l(n,t){var r=[];return mn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function p(n,r,e,u,o){var i=-1,c=n.length;for(e||(e=R),o||(o=[]);++i<c;){var f=n[i];0<r&&e(f)?1<r?p(f,r-1,e,u,o):t(o,f):u||(o[o.length]=f)}return o}function s(n,t){return n&&On(n,t,Dn);
}function h(n,t){return l(t,function(t){return U(n[t])})}function v(n,t){return n>t}function b(n,t,r,e,u){return n===t||(null==n||null==t||!H(n)&&!H(t)?n!==n&&t!==t:y(n,t,r,e,b,u))}function y(n,t,r,e,u,o){var i=Nn(n),c=Nn(t),f=i?"[object Array]":hn.call(n),a=c?"[object Array]":hn.call(t),f="[object Arguments]"==f?"[object Object]":f,a="[object Arguments]"==a?"[object Object]":a,l="[object Object]"==f,c="[object Object]"==a,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){
return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=T(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 1&r||(i=l&&pn.call(n,"__wrapped__"),f=c&&pn.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=B(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t,
r=u(i,f,r,e,o),o.pop(),r)}function g(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?d:r)(n)}function _(n,t){return n<t}function j(n,t){var r=-1,e=M(n)?Array(n.length):[];return mn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function d(n){var t=_n(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&b(n[u],r[u],3)))return false}return true}}function m(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function O(n){return xn(I(n,void 0,X),n+"");
}function x(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function A(n){return x(n,0,n.length)}function E(n,t){var r;return mn(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function w(n,r){return C(r,function(n,r){return r.func.apply(r.thisArg,t([n],r.args))},n)}function k(n,t,r){var e=!r;r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=Z;if(c===Z&&(c=n[i]),e)r[i]=c;else{var f=r,a=f[i];pn.call(f,i)&&J(a,c)&&(c!==Z||i in f)||(f[i]=c);
}}return r}function N(n){return O(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function F(n){return function(){var t=arguments,r=dn(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function S(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==on&&this instanceof e?u:n;++c<f;)a[c]=r[c];for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");
var u=F(n);return e}function T(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(1&r&&c>i))return false;for(var c=-1,f=true,a=2&r?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){f=false;break}if(a){if(!E(t,function(n,t){if(!P(a,t)&&(l===n||u(l,n,r,e,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!u(l,p,r,e,o)){f=false;break}}return f}function B(n,t,r,e,u,o){var i=1&r,c=Dn(n),f=c.length,a=Dn(t).length;if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:pn.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];
if(void 0!==Z||s!==h&&!u(s,h,r,e,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)),a}function R(t){return Nn(t)||n(t)}function D(n){var t=[];if(null!=n)for(var r in Object(n))t.push(r);return t}function I(n,t,r){return t=jn(t===Z?n.length-1:t,0),function(){for(var e=arguments,u=-1,o=jn(e.length-t,0),i=Array(o);++u<o;)i[u]=e[t+u];for(u=-1,
o=Array(t+1);++u<t;)o[u]=e[u];return o[t]=r(i),n.apply(this,o)}}function $(n){return(null==n?0:n.length)?p(n,1):[]}function q(n){return n&&n.length?n[0]:Z}function P(n,t,r){var e=null==n?0:n.length;r=typeof r=="number"?0>r?jn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return mn(n,g(t))}function C(n,t,r){return e(n,g(t),r,3>arguments.length,mn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Fn(n),
function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return!!V(n)&&(n=hn.call(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function V(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function H(n){return null!=n&&typeof n=="object"}function K(n){
return typeof n=="number"||H(n)&&"[object Number]"==hn.call(n)}function L(n){return typeof n=="string"||!Nn(n)&&H(n)&&"[object String]"==hn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return null==n?[]:u(n,Dn(n))}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=h(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=h(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n);return mn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;
if(i||r){var e=n(this.__wrapped__);return(e.__actions__=A(this.__actions__)).push({func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"']/g,rn=RegExp(tn.source),en=/^(?:0|[1-9]\d*)$/,un=typeof self=="object"&&self&&self.Object===Object&&self,on=typeof global=="object"&&global&&global.Object===Object&&global||un||Function("return this")(),cn=(un=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,fn=function(n){
return function(t){return null==n?Z:n[t]}}({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),an=Array.prototype,ln=Object.prototype,pn=ln.hasOwnProperty,sn=0,hn=ln.toString,vn=on._,bn=Object.create,yn=ln.propertyIsEnumerable,gn=on.isFinite,_n=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),jn=Math.max,dn=function(){function n(){}return function(t){return V(t)?bn?bn(t):(n.prototype=t,t=new n,n.prototype=Z,t):{}}}();i.prototype=dn(o.prototype),i.prototype.constructor=i;
var mn=function(n,t){return function(r,e){if(null==r)return r;if(!M(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(s),On=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),xn=X,An=function(n){return function(t,r,e){var u=Object(t);if(!M(t)){var o=g(r);t=Dn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=null==n?0:n.length;
if(!e)return-1;r=null==r?0:Fn(r),0>r&&(r=jn(e+r,0));n:{for(t=g(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),En=O(function(n,t,r){return S(n,t,r)}),wn=O(function(n,t){return c(n,1,t)}),kn=O(function(n,t,r){return c(n,Sn(t)||0,r)}),Nn=Array.isArray,Fn=Number,Sn=Number,Tn=N(function(n,t){k(t,_n(t),n)}),Bn=N(function(n,t){k(t,D(t),n)}),Rn=O(function(n,t){n=Object(n);var r,e=-1,u=t.length,o=2<u?t[2]:Z;if(r=o){r=t[0];var i=t[1];if(V(o)){var c=typeof i;if("number"==c){if(c=M(o))var c=o.length,f=typeof i,c=null==c?9007199254740991:c,c=!!c&&("number"==f||"symbol"!=f&&en.test(i))&&-1<i&&0==i%1&&i<c;
}else c="string"==c&&i in o;r=!!c&&J(o[i],r)}else r=false}for(r&&(u=1);++e<u;)for(o=t[e],r=In(o),i=-1,c=r.length;++i<c;){var f=r[i],a=n[f];(a===Z||J(a,ln[f])&&!pn.call(n,f))&&(n[f]=o[f])}return n}),Dn=_n,In=D,$n=function(n){return xn(I(n,Z,$),n+"")}(function(n,t){return null==n?{}:m(n,t)});o.assignIn=Bn,o.before=G,o.bind=En,o.chain=function(n){return n=o(n),n.__chain__=true,n},o.compact=function(n){return l(n,Boolean)},o.concat=function(){var n=arguments.length;if(!n)return[];for(var r=Array(n-1),e=arguments[0];n--;)r[n-1]=arguments[n];
return t(Nn(e)?A(e):[e],p(r,1))},o.create=function(n,t){var r=dn(n);return null==t?r:Tn(r,t)},o.defaults=Rn,o.defer=wn,o.delay=kn,o.filter=function(n,t){return l(n,g(t))},o.flatten=$,o.flattenDeep=function(n){return(null==n?0:n.length)?p(n,nn):[]},o.iteratee=g,o.keys=Dn,o.map=function(n,t){return j(n,g(t))},o.matches=function(n){return d(Tn({},n))},o.mixin=Y,o.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function");return function(){return!n.apply(this,arguments)}},o.once=function(n){
return G(2,n)},o.pick=$n,o.slice=function(n,t,r){var e=null==n?0:n.length;return r=r===Z?e:+r,e?x(n,null==t?0:+t,r):[]},o.sortBy=function(n,t){var e=0;return t=g(t),j(j(n,function(n,r,u){return{value:n,index:e++,criteria:t(n,r,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1;break n}}r=0}return r||n.index-t.index}),r("value"))},o.tap=function(n,t){
return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return M(n)?n.length?A(n):[]:W(n)},o.values=W,o.extend=Bn,Y(o,o),o.clone=function(n){return V(n)?Nn(n)?A(n):k(n,_n(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,fn):n},o.every=function(n,t,r){return t=r?Z:t,f(n,g(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&pn.call(n,t)},o.head=q,o.identity=X,o.indexOf=P,o.isArguments=n,o.isArray=Nn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==hn.call(n);
},o.isDate=function(n){return H(n)&&"[object Date]"==hn.call(n)},o.isEmpty=function(t){return M(t)&&(Nn(t)||L(t)||U(t.splice)||n(t))?!t.length:!_n(t).length},o.isEqual=function(n,t){return b(n,t)},o.isFinite=function(n){return typeof n=="number"&&gn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return H(n)&&"[object RegExp]"==hn.call(n)},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){
var t=null==n?0:n.length;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?a(n,X,v):Z},o.min=function(n){return n&&n.length?a(n,X,_):Z},o.noConflict=function(){return on._===this&&(on._=vn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=M(n)?n:_n(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,E(n,g(t))},o.uniqueId=function(n){var t=++sn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){
var n={};return s(o,function(t,r){pn.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.17.5",mn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:an)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(Nn(u)?u:[],n)}return this[r](function(r){return t.apply(Nn(r)?r:[],n);
})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return w(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(on._=o, define(function(){return o})):cn?((cn.exports=o)._=o,un._=o):on._=o}).call(this);

1045
dist/lodash.fp.js vendored

File diff suppressed because it is too large Load Diff

21
dist/lodash.fp.min.js vendored
View File

@@ -1,21 +0,0 @@
(function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.fp=e():t.fp=e()})(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){function n(t,e){return i(t,t,e)}var i=r(1);"function"==typeof _&&"function"==typeof _.runInContext&&(_=n(_.runInContext())),
t.exports=n},function(t,e,r){function n(t,e){return 2==e?function(e,r){return t.apply(void 0,arguments)}:function(e){return t.apply(void 0,arguments)}}function i(t,e){return 2==e?function(e,r){return t(e,r)}:function(e){return t(e)}}function a(t){for(var e=t?t.length:0,r=Array(e);e--;)r[e]=t[e];return r}function o(t){return function(e){return t({},e)}}function s(t,e){return function(){for(var r=arguments.length,n=r-1,i=Array(r);r--;)i[r]=arguments[r];var a=i[e],o=i.slice(0,e);return a&&d.apply(o,a),
e!=n&&d.apply(o,i.slice(e+1)),t.apply(this,o)}}function l(t,e){return function(){var r=arguments.length;if(r){for(var n=Array(r);r--;)n[r]=arguments[r];var i=n[0]=e.apply(void 0,n);return t.apply(void 0,n),i}}}function u(t,e,r,d){function c(t,e){if(B.cap){var r=p.iterateeRearg[t];if(r)return x(e,r);var n=!k&&p.iterateeAry[t];if(n)return W(e,n)}return e}function h(t,e,r){return E||B.curry&&r>1?z(e,r):e}function g(t,e,r){if(B.fixed&&(F||!p.skipFixed[t])){var n=p.methodSpread[t],i=n&&n.start;return void 0===i?S(e,r):s(e,i);
}return e}function y(t,e,r){return B.rearg&&r>1&&(M||!p.skipRearg[t])?V(e,p.methodRearg[t]||p.aryRearg[r]):e}function m(t,e){e=G(e);for(var r=-1,n=e.length,i=n-1,a=D(Object(t)),o=a;null!=o&&++r<n;){var s=e[r],l=o[s];null==l||K(l)||T(l)||_(l)||(o[s]=D(r==i?l:Object(l))),o=o[s]}return a}function v(t){return Q.runInContext.convert(t)(void 0)}function A(t,e){var r=p.aliasToReal[t]||t,n=p.remap[r]||r,i=d;return function(t){return u(k?C:L,r,k?C[n]:e,w(w({},i),t))}}function W(t,e){return I(t,function(t){
return"function"==typeof t?i(t,e):t})}function x(t,e){return I(t,function(t){var r=e.length;return n(V(i(t,r),e),r)})}function I(t,e){return function(){var r=arguments.length;if(!r)return t();for(var n=Array(r);r--;)n[r]=arguments[r];var i=B.rearg?0:r-1;return n[i]=e(n[i]),t.apply(void 0,n)}}function R(t,e){var r,n=p.aliasToReal[t]||t,i=e,s=J[n];return s?i=s(e):B.immutable&&(p.mutate.array[n]?i=l(e,a):p.mutate.object[n]?i=l(e,o(e)):p.mutate.set[n]&&(i=l(e,m))),q(H,function(t){return q(p.aryMethod[t],function(e){
if(n==e){var a=p.methodSpread[n];return r=a&&a.afterRearg?g(n,y(n,i,t),t):y(n,g(n,i,t),t),r=c(n,r),r=h(n,r,t),!1}}),!r}),r||(r=i),r==e&&(r=E?z(r,1):function(){return e.apply(this,arguments)}),r.convert=A(n,e),p.placeholder[n]&&(O=!0,r.placeholder=e.placeholder=j),r}var O,k="function"==typeof e,b=e===Object(e);if(b&&(d=r,r=e,e=void 0),null==r)throw new TypeError;d||(d={});var B={cap:!("cap"in d)||d.cap,curry:!("curry"in d)||d.curry,fixed:!("fixed"in d)||d.fixed,immutable:!("immutable"in d)||d.immutable,
rearg:!("rearg"in d)||d.rearg},E="curry"in d&&d.curry,F="fixed"in d&&d.fixed,M="rearg"in d&&d.rearg,j=k?r:f,C=k?r.runInContext():void 0,L=k?r:{ary:t.ary,assign:t.assign,clone:t.clone,curry:t.curry,forEach:t.forEach,isArray:t.isArray,isError:t.isError,isFunction:t.isFunction,isWeakMap:t.isWeakMap,iteratee:t.iteratee,keys:t.keys,rearg:t.rearg,toInteger:t.toInteger,toPath:t.toPath},S=L.ary,w=L.assign,D=L.clone,z=L.curry,q=L.forEach,P=L.isArray,T=L.isError,K=L.isFunction,_=L.isWeakMap,N=L.keys,V=L.rearg,U=L.toInteger,G=L.toPath,H=N(p.aryMethod),J={
castArray:function(t){return function(){var e=arguments[0];return P(e)?t(a(e)):t.apply(void 0,arguments)}},iteratee:function(t){return function(){var e=arguments[0],r=arguments[1],n=t(e,r),a=n.length;return B.cap&&"number"==typeof r?(r=r>2?r-2:1,a&&a<=r?n:i(n,r)):n}},mixin:function(t){return function(e){var r=this;if(!K(r))return t(r,Object(e));var n=[];return q(N(e),function(t){K(e[t])&&n.push([t,r.prototype[t]])}),t(r,Object(e)),q(n,function(t){var e=t[1];K(e)?r.prototype[t[0]]=e:delete r.prototype[t[0]];
}),r}},nthArg:function(t){return function(e){var r=e<0?1:U(e)+1;return z(t(e),r)}},rearg:function(t){return function(e,r){var n=r?r.length:0;return z(t(e,r),n)}},runInContext:function(e){return function(r){return u(t,e(r),d)}}};if(!b)return R(e,r);var Q=r,X=[];return q(H,function(t){q(p.aryMethod[t],function(t){var e=Q[p.remap[t]||t];e&&X.push([t,R(t,e)])})}),q(N(Q),function(t){var e=Q[t];if("function"==typeof e){for(var r=X.length;r--;)if(X[r][0]==t)return;e.convert=A(t,e),X.push([t,e])}}),q(X,function(t){
Q[t[0]]=t[1]}),Q.convert=v,O&&(Q.placeholder=j),q(N(Q),function(t){q(p.realToAlias[t]||[],function(e){Q[e]=Q[t]})}),Q}var p=r(2),f=r(3),d=Array.prototype.push;t.exports=u},function(t,e){e.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",
allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",
propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},e.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],
2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],
3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],
4:["fill","setWith","updateWith"]},e.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},e.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,
transform:2},e.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},e.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],
sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},e.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},e.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,
pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},e.placeholder={bind:!0,bindKey:!0,curry:!0,curryRight:!0,partial:!0,partialRight:!0},e.realToAlias=function(){var t=Object.prototype.hasOwnProperty,r=e.aliasToReal,n={};
for(var i in r){var a=r[i];t.call(n,a)?n[a].push(i):n[a]=[i]}return n}(),e.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",
mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},e.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},e.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,
lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},function(t,e){t.exports={}}])});

17097
dist/lodash.js vendored

File diff suppressed because it is too large Load Diff

137
dist/lodash.min.js vendored
View File

@@ -1,137 +0,0 @@
/**
* @license
* Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
*/
;(function(){function n(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function t(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function r(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&false!==t(n[r],r,n););return n}function e(n,t){for(var r=null==n?0:n.length;r--&&false!==t(n[r],r,n););return n}function u(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return false;
return true}function i(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function o(n,t){return!(null==n||!n.length)&&-1<v(n,t,0)}function f(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return true;return false}function c(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function a(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function l(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);
return r}function s(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function h(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return true;return false}function p(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,false}),e}function _(n,t,r,e){var u=n.length;for(r+=e?1:-1;e?r--:++r<u;)if(t(n[r],r,n))return r;return-1}function v(n,t,r){if(t===t)n:{--r;for(var e=n.length;++r<e;)if(n[r]===t){n=r;break n}n=-1}else n=_(n,d,r);return n}function g(n,t,r,e){
--r;for(var u=n.length;++r<u;)if(e(n[r],t))return r;return-1}function d(n){return n!==n}function y(n,t){var r=null==n?0:n.length;return r?m(n,t)/r:F}function b(n){return function(t){return null==t?T:t[n]}}function x(n){return function(t){return null==n?T:n[t]}}function j(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=false,n):t(r,n,u,i)}),r}function w(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function m(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==T&&(r=r===T?i:r+i)}return r;
}function A(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function k(n,t){return c(t,function(t){return[t,n[t]]})}function E(n){return function(t){return n(t)}}function S(n,t){return c(t,function(t){return n[t]})}function O(n,t){return n.has(t)}function I(n,t){for(var r=-1,e=n.length;++r<e&&-1<v(t,n[r],0););return r}function R(n,t){for(var r=n.length;r--&&-1<v(t,n[r],0););return r}function z(n){return"\\"+Cn[n]}function W(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n];
}),r}function B(n,t){return function(r){return n(t(r))}}function L(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function U(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function C(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function D(n){if(Rn.test(n)){for(var t=On.lastIndex=0;On.test(n);)++t;n=t}else n=Qn(n);return n}function M(n){return Rn.test(n)?n.match(On)||[]:n.split("");
}var T,$=1/0,F=NaN,N=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],P=/\b__p\+='';/g,Z=/\b(__p\+=)''\+/g,q=/(__e\(.*?\)|\b__t\))\+'';/g,V=/&(?:amp|lt|gt|quot|#39);/g,K=/[&<>"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,kn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",En=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+kn+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={};
Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false;
var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true,
Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un,Cn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Dn=parseFloat,Mn=parseInt,Tn=typeof global=="object"&&global&&global.Object===Object&&global,$n=typeof self=="object"&&self&&self.Object===Object&&self,Fn=Tn||$n||Function("return this")(),Nn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Pn=Nn&&typeof module=="object"&&module&&!module.nodeType&&module,Zn=Pn&&Pn.exports===Nn,qn=Zn&&Tn.process;
n:{try{Un=qn&&qn.binding&&qn.binding("util");break n}catch(n){}Un=void 0}var Vn=Un&&Un.isArrayBuffer,Kn=Un&&Un.isDate,Gn=Un&&Un.isMap,Hn=Un&&Un.isRegExp,Jn=Un&&Un.isSet,Yn=Un&&Un.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I",
"\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C",
"\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i",
"\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S",
"\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe",
"\u0149":"'n","\u017f":"s"}),nt=x({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}),tt=x({"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'"}),rt=function x(mn){function An(n){if(du(n)&&!of(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(ii.call(n,"__wrapped__"))return $e(n)}return new On(n)}function kn(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,
this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Cn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function $n(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new $n;++t<r;)this.add(n[t])}function Pn(n){
this.size=(this.__data__=new Tn(n)).size}function qn(n,t){var r,e=of(n),u=!e&&uf(n),i=!e&&!u&&cf(n),o=!e&&!u&&!i&&pf(n),u=(e=e||u||i||o)?A(n.length,Xu):[],f=u.length;for(r in n)!t&&!ii.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Se(r,f))||u.push(r);return u}function Qn(n){var t=n.length;return t?n[ir(0,t-1)]:T}function et(n,t){return Ce(Ur(n),pt(t,0,n.length))}function ut(n){return Ce(Ur(n))}function it(n,t,r){(r===T||au(n[t],r))&&(r!==T||t in n)||st(n,t,r);
}function ot(n,t,r){var e=n[t];ii.call(n,t)&&au(e,r)&&(r!==T||t in n)||st(n,t,r)}function ft(n,t){for(var r=n.length;r--;)if(au(n[r][0],t))return r;return-1}function ct(n,t,r,e){return eo(n,function(n,u,i){t(e,n,r(n),i)}),e}function at(n,t){return n&&Cr(t,zu(t),n)}function lt(n,t){return n&&Cr(t,Wu(t),n)}function st(n,t,r){"__proto__"==t&&mi?mi(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function ht(n,t){for(var r=-1,e=t.length,u=Vu(e),i=null==n;++r<e;)u[r]=i?T:Iu(n,t[r]);return u;
}function pt(n,t,r){return n===n&&(r!==T&&(n=n<=r?n:r),t!==T&&(n=n>=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!gu(n))return n;if(u=of(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=_o(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(cf(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=ke(n,s,c)}}if(o||(o=new Pn),
i=o.get(n))return i;if(o.set(n,f),hf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(lf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Wu:zu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=zu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Yu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ni("Expected a function");
return yo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,E(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++u<l;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(a&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function bt(n,t){var r=true;return eo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function xt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===T?o===o&&!ju(o):r(o,f)))var f=o,c=i;
}return c}function jt(n,t){var r=[];return eo(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function wt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=Ee),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?wt(f,t-1,r,e,u):a(u,f):e||(u[u.length]=f)}return u}function mt(n,t){return n&&io(n,t,zu)}function At(n,t){return n&&oo(n,t,zu)}function kt(n,t){return i(t,function(t){return pu(n[t])})}function Et(n,t){t=Sr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[De(t[r++])];return r&&r==e?n:T}function St(n,t,r){return t=t(n),
of(n)?t:a(t,r(n))}function Ot(n){if(null==n)n=n===T?"[object Undefined]":"[object Null]";else if(wi&&wi in Yu(n)){var t=ii.call(n,wi),r=n[wi];try{n[wi]=T;var e=true}catch(n){}var u=ci.call(n);e&&(t?n[wi]=r:delete n[wi]),n=u}else n=ci.call(n);return n}function It(n,t){return n>t}function Rt(n,t){return null!=n&&ii.call(n,t)}function zt(n,t){return null!=n&&t in Yu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Vu(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,E(t))),s=Ui(p.length,s),
l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;if(v?!O(v,d):!e(h,d,r)){for(a=i;--a;){var y=l[a];if(y?!O(y,d):!e(n[a],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Bt(n,t,r){var e={};return mt(n,function(n,u,i){t(e,r(n),u,i)}),e}function Lt(t,r,e){return r=Sr(r,t),t=2>r.length?t:Et(t,hr(r,0,-1)),r=null==t?t:t[De(qe(r))],null==r?T:n(r,t,e)}function Ut(n){return du(n)&&"[object Arguments]"==Ot(n)}function Ct(n){
return du(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return du(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!du(n)&&!du(t))t=n!==n&&t!==t;else n:{var i=of(n),o=of(t),f=i?"[object Array]":_o(n),c=o?"[object Array]":_o(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&cf(n)){if(!cf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Pn),t=i||pf(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{
if(!(1&r)&&(i=a&&ii.call(n,"__wrapped__"),f=o&&ii.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Pn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Pn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ii.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++a<o;){var l=f[a],h=n[l],p=t[l];if(e)var _=i?e(p,h,l,t,n,u):e(h,p,l,n,t,u);if(_===T?h!==p&&!Mt(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l);
}c&&!s&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),u.delete(n),u.delete(t),t=c}}else t=false;else t=false}}return t}function Tt(n){return du(n)&&"[object Map]"==_o(n)}function $t(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=Yu(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return false}for(;++u<i;){var f=r[u],c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===T&&!(c in n))return false;
}else{if(f=new Pn,e)var s=e(a,l,c,n,t,f);if(s===T?!Mt(l,a,3,e,f):!s)return false}}return true}function Ft(n){return!(!gu(n)||fi&&fi in n)&&(pu(n)?si:dn).test(Me(n))}function Nt(n){return du(n)&&"[object RegExp]"==Ot(n)}function Pt(n){return du(n)&&"[object Set]"==_o(n)}function Zt(n){return du(n)&&vu(n.length)&&!!Bn[Ot(n)]}function qt(n){return typeof n=="function"?n:null==n?Tu:typeof n=="object"?of(n)?Jt(n[0],n[1]):Ht(n):Pu(n)}function Vt(n){if(!ze(n))return Bi(n);var t,r=[];for(t in Yu(n))ii.call(n,t)&&"constructor"!=t&&r.push(t);
return r}function Kt(n,t){return n<t}function Gt(n,t){var r=-1,e=lu(n)?Vu(n.length):[];return eo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Ht(n){var t=xe(n);return 1==t.length&&t[0][2]?We(t[0][0],t[0][1]):function(r){return r===n||$t(r,n,t)}}function Jt(n,t){return Ie(n)&&t===t&&!gu(t)?We(De(n),t):function(r){var e=Iu(r,n);return e===T&&e===t?Ru(r,n):Mt(t,e,3)}}function Yt(n,t,r,e,u){n!==t&&io(t,function(i,o){if(gu(i)){u||(u=new Pn);var f=u,c="__proto__"==o?T:n[o],a="__proto__"==o?T:t[o],l=f.get(a);
if(l)it(n,o,l);else{var l=e?e(c,a,o+"",n,t,f):T,s=l===T;if(s){var h=of(a),p=!h&&cf(a),_=!h&&!p&&pf(a),l=a;h||p||_?of(c)?l=c:su(c)?l=Ur(c):p?(s=false,l=Ir(a,true)):_?(s=false,l=zr(a,true)):l=[]:bu(a)||uf(a)?(l=c,uf(c)?l=Su(c):(!gu(c)||r&&pu(c))&&(l=Ae(a))):s=false}s&&(f.set(a,l),Yt(l,a,r,e,f),f.delete(a)),it(n,o,l)}}else f=e?e("__proto__"==o?T:n[o],i,o+"",n,t,u):T,f===T&&(f=i),it(n,o,f)},Wu)}function Qt(n,t){var r=n.length;if(r)return t+=0>t?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[Tu],E(ye())),
n=Gt(n,function(n){return{a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Wr(u[e],i[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return Ru(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=Et(n,o);r(f,o)&&lr(i,Sr(o,n),f)}return i}function rr(n){return function(t){return Et(t,n)}}function er(n,t,r,e){var u=e?g:v,i=-1,o=t.length,f=n;
for(n===t&&(t=Ur(t)),r&&(f=c(n,E(r)));++i<o;)for(var a=0,l=t[i],l=r?r(l):l;-1<(a=u(f,l,a,e));)f!==n&&bi.call(f,a,1),bi.call(n,a,1);return n}function ur(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];if(r==e||u!==i){var i=u;Se(u)?bi.call(n,u,1):xr(n,u)}}}function ir(n,t){return n+Oi(Mi()*(t-n+1))}function or(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=Oi(t/2))&&(n+=n);while(t);return r}function fr(n,t){return bo(Be(n,t,Tu),n+"")}function cr(n){return Qn(Lu(n))}function ar(n,t){
var r=Lu(n);return Ce(r,pt(t,0,r.length))}function lr(n,t,r,e){if(!gu(n))return n;t=Sr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=De(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):T;a===T&&(a=gu(l)?l:Se(t[u+1])?[]:{})}ot(f,c,a),f=f[c]}return n}function sr(n){return Ce(Lu(n))}function hr(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Vu(u);++e<u;)r[e]=n[e+t];return r}function pr(n,t){var r;return eo(n,function(n,e,u){return r=t(n,e,u),
!r}),!!r}function _r(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!ju(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return vr(n,t,Tu,r)}function vr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=ju(t),a=t===T;u<i;){var l=Oi((u+i)/2),s=r(n[l]),h=s!==T,p=null===s,_=s===s,v=ju(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Ui(i,4294967294)}function gr(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){
var o=n[r],f=t?t(o):o;if(!r||!au(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function dr(n){return typeof n=="number"?n:ju(n)?F:+n}function yr(n){if(typeof n=="string")return n;if(of(n))return c(n,yr)+"";if(ju(n))return to?to.call(n):"";var t=n+"";return"0"==t&&1/n==-$?"-0":t}function br(n,t,r){var e=-1,u=o,i=n.length,c=true,a=[],l=a;if(r)c=false,u=f;else if(200<=i){if(u=t?null:lo(n))return U(u);c=false,u=O,l=new Nn}else l=t?[]:a;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(c&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;
t&&l.push(h),a.push(s)}else u(l,h,r)||(l!==a&&l.push(h),a.push(s))}return a}function xr(n,t){return t=Sr(t,n),n=2>t.length?n:Et(n,hr(t,0,-1)),null==n||delete n[De(qe(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?hr(n,e?0:i,e?i+1:u):hr(n,e?i+1:0,e?u:i)}function wr(n,t){var r=n;return r instanceof Un&&(r=r.value()),l(t,function(n,t){return t.func.apply(t.thisArg,a([n],t.args))},r)}function mr(n,t,r){var e=n.length;if(2>e)return e?br(n[0]):[];for(var u=-1,i=Vu(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=yt(i[u]||o,n[f],t,r));
return br(wt(i,1),t,r)}function Ar(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:T);return o}function kr(n){return su(n)?n:[]}function Er(n){return typeof n=="function"?n:Tu}function Sr(n,t){return of(n)?n:Ie(n,t)?[n]:xo(Ou(n))}function Or(n,t,r){var e=n.length;return r=r===T?e:r,!t&&r>=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=vi?vi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new _i(t).set(new _i(n)),
t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=ju(n),o=t!==T,f=null===t,c=t===t,a=ju(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Br(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Li(i-o,0),l=Vu(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];
return l}function Lr(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Li(i-f,0),s=Vu(l+a);for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Ur(n,t){var r=-1,e=n.length;for(t||(t=Vu(e));++r<e;)t[r]=n[r];return t}function Cr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):T;c===T&&(c=n[f]),u?st(r,f,c):ot(r,f,c)}return r}function Dr(n,t){return Cr(n,ho(n),t)}function Mr(n,t){return Cr(n,po(n),t);
}function Tr(n,r){return function(e,u){var i=of(e)?t:ct,o=r?r():{};return i(e,n,ye(u,2),o)}}function $r(n){return fr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:T,o=2<u?r[2]:T,i=3<n.length&&typeof i=="function"?(u--,i):T;for(o&&Oe(r[0],r[1],o)&&(i=3>u?T:i,u=1),t=Yu(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Fr(n,t){return function(r,e){if(null==r)return r;if(!lu(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=Yu(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function Nr(n){return function(t,r,e){
var u=-1,i=Yu(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break}return t}}function Pr(n,t,r){function e(){return(this&&this!==Fn&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Vr(n);return e}function Zr(n){return function(t){t=Ou(t);var r=Rn.test(t)?M(t):T,e=r?r[0]:t.charAt(0);return t=r?Or(r,1).join(""):t.slice(1),e[n]()+t}}function qr(n){return function(t){return l(Du(Cu(t).replace(En,"")),n,"")}}function Vr(n){return function(){var t=arguments;switch(t.length){
case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=ro(n.prototype),t=n.apply(r,t);return gu(t)?t:r}}function Kr(t,r,e){function u(){for(var o=arguments.length,f=Vu(o),c=o,a=de(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:L(f,a),
o-=c.length,o<e?ue(t,r,Jr,u.placeholder,T,f,c,T,T,e-o):n(this&&this!==Fn&&this instanceof u?i:t,this,f)}var i=Vr(t);return u}function Gr(n){return function(t,r,e){var u=Yu(t);if(!lu(t)){var i=ye(r,3);t=zu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:T}}function Hr(n){return pe(function(t){var r=t.length,e=r,u=On.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ni("Expected a function");if(u&&!o&&"wrapper"==ge(i))var o=new On([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=ge(i),f="wrapper"==u?so(i):T,o=f&&Re(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[ge(f[0])].apply(o,f[3]):1==i.length&&Re(i)?o[u]():o.thru(i);
return function(){var n=arguments,e=n[0];if(o&&1==n.length&&of(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Jr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Vu(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=de(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Br(y,e,u,_)),i&&(y=Lr(y,i,o,_)),d-=x,_&&d<a)return j=L(y,j),ue(n,t,Jr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Ui(f.length,x),m=Ur(y);w--;){
var A=f[w];y[w]=Se(A,x)?m[A]:T}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==Fn&&this instanceof l&&(b=g||Vr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?T:Vr(n);return l}function Yr(n,t){return function(r,e){return Bt(r,n,t(e))}}function Qr(n,t){return function(r,e){var u;if(r===T&&e===T)return t;if(r!==T&&(u=r),e!==T){if(u===T)return e;typeof r=="string"||typeof e=="string"?(r=yr(r),e=yr(e)):(r=dr(r),e=dr(e)),u=n(r,e)}return u}}function Xr(t){return pe(function(r){
return r=c(r,E(ye())),fr(function(e){var u=this;return t(r,function(t){return n(t,u,e)})})})}function ne(n,t){t=t===T?" ":yr(t);var r=t.length;return 2>r?r?or(t,n):t:(r=or(t,Si(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Vu(l+c),h=this&&this!==Fn&&this instanceof i?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++r];return n(h,o?e:this,s)}var o=1&r,f=Vr(t);return i}function re(n){return function(t,r,e){
e&&typeof e!="number"&&Oe(t,r,e)&&(r=e=T),t=mu(t),r===T?(r=t,t=0):r=mu(r),e=e===T?t<r?1:-1:mu(e);var u=-1;r=Li(Si((r-t)/(e||1)),0);for(var i=Vu(r);r--;)i[n?r:++u]=t,t+=e;return i}}function ee(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=Eu(t),r=Eu(r)),n(t,r)}}function ue(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:T;o=l?T:o;var h=l?i:T;return i=l?T:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(T,u),Re(n)&&go(r,u),r.placeholder=e,Le(r,n,t)}function ie(n){
var t=Ju[n];return function(n,r){if(n=Eu(n),r=null==r?0:Ui(Au(r),292)){var e=(Ou(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(Ou(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function oe(n){return function(t){var r=_o(t);return"[object Map]"==r?W(t):"[object Set]"==r?C(t):k(t,n(t))}}function fe(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ni("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=T),o=o===T?o:Li(Au(o),0),f=f===T?f:Au(f),a-=u?u.length:0,64&t){
var l=e,s=u;e=u=T}var h=c?T:so(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ui(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1],
r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),Le((h?fo:go)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||au(n,ri[r])&&!ii.call(e,r)?t:n}function ae(n,t,r,e,u,i){return gu(n)&&gu(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return bu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new Nn:T;
for(i.set(n,t),i.set(t,n);++c<f;){var s=n[c],p=t[c];if(e)var _=o?e(p,s,c,t,n,i):e(s,p,c,n,t,i);if(_!==T){if(_)continue;a=false;break}if(l){if(!h(t,function(n,t){if(!O(l,t)&&(s===n||u(s,n,r,e,i)))return l.push(t)})){a=false;break}}else if(s!==p&&!u(s,p,r,e,i)){a=false;break}}return i.delete(n),i.delete(t),a}function he(n,t,r,e,u,i,o){switch(r){case"[object DataView]":if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)break;n=n.buffer,t=t.buffer;case"[object ArrayBuffer]":if(n.byteLength!=t.byteLength||!i(new _i(n),new _i(t)))break;
return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return au(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=W;case"[object Set]":if(f||(f=U),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=se(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(no)return no.call(n)==no.call(t)}return false}function pe(n){return bo(Be(n,T,Pe),n+"")}function _e(n){
return St(n,zu,ho)}function ve(n){return St(n,Wu,po)}function ge(n){for(var t=n.name+"",r=Ki[t],e=ii.call(Ki,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function de(n){return(ii.call(An,"placeholder")?An:n).placeholder}function ye(){var n=An.iteratee||$u,n=n===$u?qt:n;return arguments.length?n(arguments[0],arguments[1]):n}function be(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
}function xe(n){for(var t=zu(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,u===u&&!gu(u)]}return t}function je(n,t){var r=null==n?T:n[t];return Ft(r)?r:T}function we(n,t,r){t=Sr(t,n);for(var e=-1,u=t.length,i=false;++e<u;){var o=De(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&vu(u)&&Se(o,u)&&(of(n)||uf(n)))}function me(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&ii.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ae(n){
return typeof n.constructor!="function"||ze(n)?{}:ro(gi(n))}function ke(n,t,r){var e=n.constructor;switch(t){case"[object ArrayBuffer]":return Rr(n);case"[object Boolean]":case"[object Date]":return new e(+n);case"[object DataView]":return t=r?Rr(n.buffer):n.buffer,new n.constructor(t,n.byteOffset,n.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
case"[object Uint16Array]":case"[object Uint32Array]":return zr(n,r);case"[object Map]":return new e;case"[object Number]":case"[object String]":return new e(n);case"[object RegExp]":return t=new n.constructor(n.source,_n.exec(n)),t.lastIndex=n.lastIndex,t;case"[object Set]":return new e;case"[object Symbol]":return no?Yu(no.call(n)):{}}}function Ee(n){return of(n)||uf(n)||!!(xi&&n&&n[xi])}function Se(n,t){var r=typeof n;return t=null==t?9007199254740991:t,!!t&&("number"==r||"symbol"!=r&&bn.test(n))&&-1<n&&0==n%1&&n<t;
}function Oe(n,t,r){if(!gu(r))return false;var e=typeof t;return!!("number"==e?lu(r)&&Se(t,r.length):"string"==e&&t in r)&&au(r[t],n)}function Ie(n,t){if(of(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!ju(n))||(nn.test(n)||!X.test(n)||null!=t&&n in Yu(t))}function Re(n){var t=ge(n),r=An[t];return typeof r=="function"&&t in Un.prototype&&(n===r||(t=so(r),!!t&&n===t[0]))}function ze(n){var t=n&&n.constructor;return n===(typeof t=="function"&&t.prototype||ri)}function We(n,t){
return function(r){return null!=r&&(r[n]===t&&(t!==T||n in Yu(r)))}}function Be(t,r,e){return r=Li(r===T?t.length-1:r,0),function(){for(var u=arguments,i=-1,o=Li(u.length-r,0),f=Vu(o);++i<o;)f[i]=u[r+i];for(i=-1,o=Vu(r+1);++i<r;)o[i]=u[i];return o[r]=e(f),n(t,this,o)}}function Le(n,t,r){var e=t+"";t=bo;var u,i=Te;return u=(u=e.match(an))?u[1].split(ln):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],r=r.join(2<i?", ":" "),e=e.replace(cn,"{\n/* [wrapped with "+r+"] */\n")),t(n,e)}function Ue(n){
var t=0,r=0;return function(){var e=Ci(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(T,arguments)}}function Ce(n,t){var r=-1,e=n.length,u=e-1;for(t=t===T?e:t;++r<t;){var e=ir(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function De(n){if(typeof n=="string"||ju(n))return n;var t=n+"";return"0"==t&&1/n==-$?"-0":t}function Me(n){if(null!=n){try{return ui.call(n)}catch(n){}return n+""}return""}function Te(n,t){return r(N,function(r){var e="_."+r[0];t&r[1]&&!o(n,e)&&n.push(e);
}),n.sort()}function $e(n){if(n instanceof Un)return n.clone();var t=new On(n.__wrapped__,n.__chain__);return t.__actions__=Ur(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Fe(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Ne(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Au(r),u=0>r?Li(e+u,0):Ui(u,e-1)),_(n,ye(t,3),u,true)}function Pe(n){return(null==n?0:n.length)?wt(n,1):[]}function Ze(n){
return n&&n.length?n[0]:T}function qe(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ve(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ke(n){return null==n?n:Ti.call(n)}function Ge(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(su(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function He(t,r){if(!t||!t.length)return[];var e=Ge(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Je(n){return n=An(n),n.__chain__=true,n}function Ye(n,t){
return t(n)}function Qe(){return this}function Xe(n,t){return(of(n)?r:eo)(n,ye(t,3))}function nu(n,t){return(of(n)?e:uo)(n,ye(t,3))}function tu(n,t){return(of(n)?c:Gt)(n,ye(t,3))}function ru(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function eu(n,t){var r;if(typeof t!="function")throw new ni("Expected a function");return n=Au(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function uu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=uu.placeholder,
n}function iu(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Ko();if(u(n))return o(n);var r,e=yo;r=n-_,n=t-(n-p),r=g?Ui(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Ko(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=yo(i,t),v?e(n):s;if(g)return h=yo(i,t),e(p)}return h===T&&(h=yo(i,t)),
s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ni("Expected a function");return t=Eu(t)||0,gu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(Eu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&ao(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Ko())},f}function fu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ni("Expected a function");
return r.cache=new(fu.Cache||$n),r}function cu(n){if(typeof n!="function")throw new ni("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function au(n,t){return n===t||n!==n&&t!==t}function lu(n){return null!=n&&vu(n.length)&&!pu(n)}function su(n){return du(n)&&lu(n)}function hu(n){if(!du(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!bu(n);
}function pu(n){return!!gu(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function _u(n){return typeof n=="number"&&n==Au(n)}function vu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n}function gu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function du(n){return null!=n&&typeof n=="object"}function yu(n){return typeof n=="number"||du(n)&&"[object Number]"==Ot(n)}function bu(n){return!(!du(n)||"[object Object]"!=Ot(n))&&(n=gi(n),
null===n||(n=ii.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ui.call(n)==ai))}function xu(n){return typeof n=="string"||!of(n)&&du(n)&&"[object String]"==Ot(n)}function ju(n){return typeof n=="symbol"||du(n)&&"[object Symbol]"==Ot(n)}function wu(n){if(!n)return[];if(lu(n))return xu(n)?M(n):Ur(n);if(ji&&n[ji]){n=n[ji]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=_o(n),("[object Map]"==t?W:"[object Set]"==t?U:Lu)(n)}function mu(n){return n?(n=Eu(n),
n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Au(n){n=mu(n);var t=n%1;return n===n?t?n-t:n:0}function ku(n){return n?pt(Au(n),0,4294967295):0}function Eu(n){if(typeof n=="number")return n;if(ju(n))return F;if(gu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=gu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Mn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Su(n){return Cr(n,Wu(n))}function Ou(n){return null==n?"":yr(n);
}function Iu(n,t,r){return n=null==n?T:Et(n,t),n===T?r:n}function Ru(n,t){return null!=n&&we(n,t,zt)}function zu(n){return lu(n)?qn(n):Vt(n)}function Wu(n){if(lu(n))n=qn(n,true);else if(gu(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&ii.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Yu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,zu(n));
}function Uu(n){return Tf(Ou(n).toLowerCase())}function Cu(n){return(n=Ou(n))&&n.replace(xn,Xn).replace(Sn,"")}function Du(n,t,r){return n=Ou(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Mu(n){return function(){return n}}function Tu(n){return n}function $u(n){return qt(typeof n=="function"?n:_t(n,1))}function Fu(n,t,e){var u=zu(t),i=kt(t,u);null!=e||gu(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=kt(t,zu(t)));var o=!(gu(e)&&"chain"in e&&!e.chain),f=pu(n);return r(i,function(r){
var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Nu(){}function Pu(n){return Ie(n)?b(De(n)):rr(n)}function Zu(){return[]}function qu(){return false}mn=null==mn?Fn:rt.defaults(Fn.Object(),mn,rt.pick(Fn,Wn));var Vu=mn.Array,Ku=mn.Date,Gu=mn.Error,Hu=mn.Function,Ju=mn.Math,Yu=mn.Object,Qu=mn.RegExp,Xu=mn.String,ni=mn.TypeError,ti=Vu.prototype,ri=Yu.prototype,ei=mn["__core-js_shared__"],ui=Hu.prototype.toString,ii=ri.hasOwnProperty,oi=0,fi=function(){
var n=/[^.]+$/.exec(ei&&ei.keys&&ei.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ci=ri.toString,ai=ui.call(Yu),li=Fn._,si=Qu("^"+ui.call(ii).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),hi=Zn?mn.Buffer:T,pi=mn.Symbol,_i=mn.Uint8Array,vi=hi?hi.f:T,gi=B(Yu.getPrototypeOf,Yu),di=Yu.create,yi=ri.propertyIsEnumerable,bi=ti.splice,xi=pi?pi.isConcatSpreadable:T,ji=pi?pi.iterator:T,wi=pi?pi.toStringTag:T,mi=function(){try{var n=je(Yu,"defineProperty");
return n({},"",{}),n}catch(n){}}(),Ai=mn.clearTimeout!==Fn.clearTimeout&&mn.clearTimeout,ki=Ku&&Ku.now!==Fn.Date.now&&Ku.now,Ei=mn.setTimeout!==Fn.setTimeout&&mn.setTimeout,Si=Ju.ceil,Oi=Ju.floor,Ii=Yu.getOwnPropertySymbols,Ri=hi?hi.isBuffer:T,zi=mn.isFinite,Wi=ti.join,Bi=B(Yu.keys,Yu),Li=Ju.max,Ui=Ju.min,Ci=Ku.now,Di=mn.parseInt,Mi=Ju.random,Ti=ti.reverse,$i=je(mn,"DataView"),Fi=je(mn,"Map"),Ni=je(mn,"Promise"),Pi=je(mn,"Set"),Zi=je(mn,"WeakMap"),qi=je(Yu,"create"),Vi=Zi&&new Zi,Ki={},Gi=Me($i),Hi=Me(Fi),Ji=Me(Ni),Yi=Me(Pi),Qi=Me(Zi),Xi=pi?pi.prototype:T,no=Xi?Xi.valueOf:T,to=Xi?Xi.toString:T,ro=function(){
function n(){}return function(t){return gu(t)?di?di(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=kn.prototype,An.prototype.constructor=An,On.prototype=ro(kn.prototype),On.prototype.constructor=On,Un.prototype=ro(kn.prototype),Un.prototype.constructor=Un,Cn.prototype.clear=function(){this.__data__=qi?qi(null):{},this.size=0},Cn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
this.size-=n?1:0,n},Cn.prototype.get=function(n){var t=this.__data__;return qi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):ii.call(t,n)?t[n]:T},Cn.prototype.has=function(n){var t=this.__data__;return qi?t[n]!==T:ii.call(t,n)},Cn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=qi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():bi.call(t,n,1),
--this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1<ft(this.__data__,n)},Tn.prototype.set=function(n,t){var r=this.__data__,e=ft(r,n);return 0>e?(++this.size,r.push([n,t])):r[e][1]=t,this},$n.prototype.clear=function(){this.size=0,this.__data__={hash:new Cn,map:new(Fi||Tn),string:new Cn}},$n.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},$n.prototype.get=function(n){return be(this,n).get(n);
},$n.prototype.has=function(n){return be(this,n).has(n)},$n.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Pn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Pn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Pn.prototype.get=function(n){
return this.__data__.get(n)},Pn.prototype.has=function(n){return this.__data__.has(n)},Pn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Fi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new $n(e)}return r.set(n,t),this.size=r.size,this};var eo=Fr(mt),uo=Fr(At,true),io=Nr(),oo=Nr(true),fo=Vi?function(n,t){return Vi.set(n,t),n}:Tu,co=mi?function(n,t){return mi(n,"toString",{configurable:true,enumerable:false,value:Mu(t),writable:true})}:Tu,ao=Ai||function(n){
return Fn.clearTimeout(n)},lo=Pi&&1/U(new Pi([,-0]))[1]==$?function(n){return new Pi(n)}:Nu,so=Vi?function(n){return Vi.get(n)}:Nu,ho=Ii?function(n){return null==n?[]:(n=Yu(n),i(Ii(n),function(t){return yi.call(n,t)}))}:Zu,po=Ii?function(n){for(var t=[];n;)a(t,ho(n)),n=gi(n);return t}:Zu,_o=Ot;($i&&"[object DataView]"!=_o(new $i(new ArrayBuffer(1)))||Fi&&"[object Map]"!=_o(new Fi)||Ni&&"[object Promise]"!=_o(Ni.resolve())||Pi&&"[object Set]"!=_o(new Pi)||Zi&&"[object WeakMap]"!=_o(new Zi))&&(_o=function(n){
var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Me(n):"")switch(n){case Gi:return"[object DataView]";case Hi:return"[object Map]";case Ji:return"[object Promise]";case Yi:return"[object Set]";case Qi:return"[object WeakMap]"}return t});var vo=ei?pu:qu,go=Ue(fo),yo=Ei||function(n,t){return Fn.setTimeout(n,t)},bo=Ue(co),xo=function(n){n=fu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){
t.push(e?u.replace(hn,"$1"):r||n)}),t}),jo=fr(function(n,t){return su(n)?yt(n,wt(t,1,su,true)):[]}),wo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),ye(r,2)):[]}),mo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),T,r):[]}),Ao=fr(function(n){var t=c(n,kr);return t.length&&t[0]===n[0]?Wt(t):[]}),ko=fr(function(n){var t=qe(n),r=c(n,kr);return t===qe(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),Eo=fr(function(n){var t=qe(n),r=c(n,kr);return(t=typeof t=="function"?t:T)&&r.pop(),
r.length&&r[0]===n[0]?Wt(r,T,t):[]}),So=fr(Ve),Oo=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Io=fr(function(n){return br(wt(n,1,su,true))}),Ro=fr(function(n){var t=qe(n);return su(t)&&(t=T),br(wt(n,1,su,true),ye(t,2))}),zo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return br(wt(n,1,su,true),T,t)}),Wo=fr(function(n,t){return su(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,su))}),Lo=fr(function(n){var t=qe(n);return su(t)&&(t=T),
mr(i(n,su),ye(t,2))}),Uo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return mr(i(n,su),T,t)}),Co=fr(Ge),Do=fr(function(n){var t=n.length,t=1<t?n[t-1]:T,t=typeof t=="function"?(n.pop(),t):T;return He(n,t)}),Mo=pe(function(n){function t(t){return ht(t,n)}var r=n.length,e=r?n[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Un&&Se(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:Ye,args:[t],thisArg:T}),new On(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(T),
n})):this.thru(t)}),To=Tr(function(n,t,r){ii.call(n,r)?++n[r]:st(n,r,1)}),$o=Gr(Fe),Fo=Gr(Ne),No=Tr(function(n,t,r){ii.call(n,r)?n[r].push(t):st(n,r,[t])}),Po=fr(function(t,r,e){var u=-1,i=typeof r=="function",o=lu(t)?Vu(t.length):[];return eo(t,function(t){o[++u]=i?n(r,t,e):Lt(t,r,e)}),o}),Zo=Tr(function(n,t,r){st(n,r,t)}),qo=Tr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Vo=fr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&Oe(n,t[0],t[1])?t=[]:2<r&&Oe(t[0],t[1],t[2])&&(t=[t[0]]),
Xt(n,wt(t,1),[])}),Ko=ki||function(){return Fn.Date.now()},Go=fr(function(n,t,r){var e=1;if(r.length)var u=L(r,de(Go)),e=32|e;return fe(n,e,t,r,u)}),Ho=fr(function(n,t,r){var e=3;if(r.length)var u=L(r,de(Ho)),e=32|e;return fe(t,e,n,r,u)}),Jo=fr(function(n,t){return dt(n,1,t)}),Yo=fr(function(n,t,r){return dt(n,Eu(t)||0,r)});fu.Cache=$n;var Qo=fr(function(t,r){r=1==r.length&&of(r[0])?c(r[0],E(ye())):c(wt(r,1),E(ye()));var e=r.length;return fr(function(u){for(var i=-1,o=Ui(u.length,e);++i<o;)u[i]=r[i].call(this,u[i]);
return n(t,this,u)})}),Xo=fr(function(n,t){return fe(n,32,T,t,L(t,de(Xo)))}),nf=fr(function(n,t){return fe(n,64,T,t,L(t,de(nf)))}),tf=pe(function(n,t){return fe(n,256,T,T,T,t)}),rf=ee(It),ef=ee(function(n,t){return n>=t}),uf=Ut(function(){return arguments}())?Ut:function(n){return du(n)&&ii.call(n,"callee")&&!yi.call(n,"callee")},of=Vu.isArray,ff=Vn?E(Vn):Ct,cf=Ri||qu,af=Kn?E(Kn):Dt,lf=Gn?E(Gn):Tt,sf=Hn?E(Hn):Nt,hf=Jn?E(Jn):Pt,pf=Yn?E(Yn):Zt,_f=ee(Kt),vf=ee(function(n,t){return n<=t}),gf=$r(function(n,t){
if(ze(t)||lu(t))Cr(t,zu(t),n);else for(var r in t)ii.call(t,r)&&ot(n,r,t[r])}),df=$r(function(n,t){Cr(t,Wu(t),n)}),yf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),bf=$r(function(n,t,r,e){Cr(t,zu(t),n,e)}),xf=pe(ht),jf=fr(function(n,t){n=Yu(n);var r=-1,e=t.length,u=2<e?t[2]:T;for(u&&Oe(t[0],t[1],u)&&(e=1);++r<e;)for(var u=t[r],i=Wu(u),o=-1,f=i.length;++o<f;){var c=i[o],a=n[c];(a===T||au(a,ri[c])&&!ii.call(n,c))&&(n[c]=u[c])}return n}),wf=fr(function(t){return t.push(T,ae),n(Sf,T,t)}),mf=Yr(function(n,t,r){
null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),n[t]=r},Mu(Tu)),Af=Yr(function(n,t,r){null!=t&&typeof t.toString!="function"&&(t=ci.call(t)),ii.call(n,t)?n[t].push(r):n[t]=[r]},ye),kf=fr(Lt),Ef=$r(function(n,t,r){Yt(n,t,r)}),Sf=$r(function(n,t,r,e){Yt(n,t,r,e)}),Of=pe(function(n,t){var r={};if(null==n)return r;var e=false;t=c(t,function(t){return t=Sr(t,n),e||(e=1<t.length),t}),Cr(n,ve(n),r),e&&(r=_t(r,7,le));for(var u=t.length;u--;)xr(r,t[u]);return r}),If=pe(function(n,t){return null==n?{}:nr(n,t);
}),Rf=oe(zu),zf=oe(Wu),Wf=qr(function(n,t,r){return t=t.toLowerCase(),n+(r?Uu(t):t)}),Bf=qr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Lf=qr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Uf=Zr("toLowerCase"),Cf=qr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Df=qr(function(n,t,r){return n+(r?" ":"")+Tf(t)}),Mf=qr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),Tf=Zr("toUpperCase"),$f=fr(function(t,r){try{return n(t,T,r)}catch(n){return hu(n)?n:new Gu(n)}}),Ff=pe(function(n,t){
return r(t,function(t){t=De(t),st(n,t,Go(n[t],n))}),n}),Nf=Hr(),Pf=Hr(true),Zf=fr(function(n,t){return function(r){return Lt(r,n,t)}}),qf=fr(function(n,t){return function(r){return Lt(n,r,t)}}),Vf=Xr(c),Kf=Xr(u),Gf=Xr(h),Hf=re(),Jf=re(true),Yf=Qr(function(n,t){return n+t},0),Qf=ie("ceil"),Xf=Qr(function(n,t){return n/t},1),nc=ie("floor"),tc=Qr(function(n,t){return n*t},1),rc=ie("round"),ec=Qr(function(n,t){return n-t},0);return An.after=function(n,t){if(typeof t!="function")throw new ni("Expected a function");
return n=Au(n),function(){if(1>--n)return t.apply(this,arguments)}},An.ary=ru,An.assign=gf,An.assignIn=df,An.assignInWith=yf,An.assignWith=bf,An.at=xf,An.before=eu,An.bind=Go,An.bindAll=Ff,An.bindKey=Ho,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return of(n)?n:[n]},An.chain=Je,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(Au(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Vu(Si(r/t));e<r;)i[u++]=hr(n,e,e+=t);return i},An.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){
var i=n[t];i&&(u[e++]=i)}return u},An.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Vu(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return a(of(r)?Ur(r):[r],wt(t,1))},An.cond=function(t){var r=null==t?0:t.length,e=ye();return t=r?c(t,function(n){if("function"!=typeof n[1])throw new ni("Expected a function");return[e(n[0]),n[1]]}):[],fr(function(e){for(var u=-1;++u<r;){var i=t[u];if(n(i[0],this,e))return n(i[1],this,e)}})},An.conforms=function(n){return vt(_t(n,1))},An.constant=Mu,
An.countBy=To,An.create=function(n,t){var r=ro(n);return null==t?r:at(r,t)},An.curry=uu,An.curryRight=iu,An.debounce=ou,An.defaults=jf,An.defaultsDeep=wf,An.defer=Jo,An.delay=Yo,An.difference=jo,An.differenceBy=wo,An.differenceWith=mo,An.drop=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),hr(n,0>t?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[];
},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Au(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Au(e),0>e&&(e+=u),e=r>e?0:ku(e);r<e;)n[r++]=t;return n},An.filter=function(n,t){return(of(n)?i:jt)(n,ye(t,3))},An.flatMap=function(n,t){return wt(tu(n,t),1)},An.flatMapDeep=function(n,t){return wt(tu(n,t),$)},An.flatMapDepth=function(n,t,r){return r=r===T?1:Au(r),
wt(tu(n,t),r)},An.flatten=Pe,An.flattenDeep=function(n){return(null==n?0:n.length)?wt(n,$):[]},An.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===T?1:Au(t),wt(n,t)):[]},An.flip=function(n){return fe(n,512)},An.flow=Nf,An.flowRight=Pf,An.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){var u=n[t];e[u[0]]=u[1]}return e},An.functions=function(n){return null==n?[]:kt(n,zu(n))},An.functionsIn=function(n){return null==n?[]:kt(n,Wu(n))},An.groupBy=No,An.initial=function(n){
return(null==n?0:n.length)?hr(n,0,-1):[]},An.intersection=Ao,An.intersectionBy=ko,An.intersectionWith=Eo,An.invert=mf,An.invertBy=Af,An.invokeMap=Po,An.iteratee=$u,An.keyBy=Zo,An.keys=zu,An.keysIn=Wu,An.map=tu,An.mapKeys=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,t(n,e,u),n)}),r},An.mapValues=function(n,t){var r={};return t=ye(t,3),mt(n,function(n,e,u){st(r,e,t(n,e,u))}),r},An.matches=function(n){return Ht(_t(n,1))},An.matchesProperty=function(n,t){return Jt(n,_t(t,1))},An.memoize=fu,
An.merge=Ef,An.mergeWith=Sf,An.method=Zf,An.methodOf=qf,An.mixin=Fu,An.negate=cu,An.nthArg=function(n){return n=Au(n),fr(function(t){return Qt(t,n)})},An.omit=Of,An.omitBy=function(n,t){return Bu(n,cu(ye(t)))},An.once=function(n){return eu(2,n)},An.orderBy=function(n,t,r,e){return null==n?[]:(of(t)||(t=null==t?[]:[t]),r=e?T:r,of(r)||(r=null==r?[]:[r]),Xt(n,t,r))},An.over=Vf,An.overArgs=Qo,An.overEvery=Kf,An.overSome=Gf,An.partial=Xo,An.partialRight=nf,An.partition=qo,An.pick=If,An.pickBy=Bu,An.property=Pu,
An.propertyOf=function(n){return function(t){return null==n?T:Et(n,t)}},An.pull=So,An.pullAll=Ve,An.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,ye(r,2)):n},An.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?er(n,t,T,r):n},An.pullAt=Oo,An.range=Hf,An.rangeRight=Jf,An.rearg=tf,An.reject=function(n,t){return(of(n)?i:jt)(n,cu(ye(t,3)))},An.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=ye(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),
u.push(e))}return ur(n,u),r},An.rest=function(n,t){if(typeof n!="function")throw new ni("Expected a function");return t=t===T?t:Au(t),fr(n,t)},An.reverse=Ke,An.sampleSize=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),(of(n)?et:ar)(n,t)},An.set=function(n,t,r){return null==n?n:lr(n,t,r)},An.setWith=function(n,t,r,e){return e=typeof e=="function"?e:T,null==n?n:lr(n,t,r,e)},An.shuffle=function(n){return(of(n)?ut:sr)(n)},An.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&Oe(n,t,r)?(t=0,
r=e):(t=null==t?0:Au(t),r=r===T?e:Au(r)),hr(n,t,r)):[]},An.sortBy=Vo,An.sortedUniq=function(n){return n&&n.length?gr(n):[]},An.sortedUniqBy=function(n,t){return n&&n.length?gr(n,ye(t,2)):[]},An.split=function(n,t,r){return r&&typeof r!="number"&&Oe(n,t,r)&&(t=r=T),r=r===T?4294967295:r>>>0,r?(n=Ou(n))&&(typeof t=="string"||null!=t&&!sf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ni("Expected a function");return r=null==r?0:Li(Au(r),0),
fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Au(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n),
n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ni("Expected a function");return gu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ou(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Ye,An.toArray=wu,An.toPairs=Rf,An.toPairsIn=zf,An.toPath=function(n){return of(n)?c(n,De):ju(n)?[n]:Ur(xo(Ou(n)))},An.toPlainObject=Su,An.transform=function(n,t,e){var u=of(n),i=u||cf(n)||pf(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:gu(n)&&pu(o)?ro(gi(n)):{};
}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return ru(n,1)},An.union=Io,An.unionBy=Ro,An.unionWith=zo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=Ge,An.unzipWith=He,An.update=function(n,t,r){return null==n?n:lr(n,t,Er(r)(Et(n,t)),void 0)},An.updateWith=function(n,t,r,e){
return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,Er(r)(Et(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Wu(n))},An.without=Wo,An.words=Du,An.wrap=function(n,t){return Xo(Er(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Uo,An.zip=Co,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Do,An.entries=Rf,An.entriesIn=zf,An.extend=df,An.extendWith=yf,Fu(An,An),An.add=Yf,An.attempt=$f,An.camelCase=Wf,An.capitalize=Uu,
An.ceil=Qf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=Eu(r),r=r===r?r:0),t!==T&&(t=Eu(t),t=t===t?t:0),pt(Eu(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,zu(t))},An.deburr=Cu,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=Xf,An.endsWith=function(n,t,r){
n=Ou(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Au(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=au,An.escape=function(n){return(n=Ou(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Ou(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=of(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=$o,An.findIndex=Fe,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=Fo,An.findLastIndex=Ne,An.findLastKey=function(n,t){return p(n,ye(t,3),At);
},An.floor=nc,An.forEach=Xe,An.forEachRight=nu,An.forIn=function(n,t){return null==n?n:io(n,ye(t,3),Wu)},An.forInRight=function(n,t){return null==n?n:oo(n,ye(t,3),Wu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Iu,An.gt=rf,An.gte=ef,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=Ru,An.head=Ze,An.identity=Tu,An.includes=function(n,t,r,e){return n=lu(n)?n:Lu(n),r=r&&!e?Au(r):0,e=n.length,0>r&&(r=Li(e+r,0)),xu(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<v(n,t,r);
},An.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Au(r),0>r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=mu(t),r===T?(r=t,t=0):r=mu(r),n=Eu(n),n>=Ui(t,r)&&n<Li(t,r)},An.invoke=kf,An.isArguments=uf,An.isArray=of,An.isArrayBuffer=ff,An.isArrayLike=lu,An.isArrayLikeObject=su,An.isBoolean=function(n){return true===n||false===n||du(n)&&"[object Boolean]"==Ot(n)},An.isBuffer=cf,An.isDate=af,An.isElement=function(n){return du(n)&&1===n.nodeType&&!bu(n)},An.isEmpty=function(n){
if(null==n)return true;if(lu(n)&&(of(n)||typeof n=="string"||typeof n.splice=="function"||cf(n)||pf(n)||uf(n)))return!n.length;var t=_o(n);if("[object Map]"==t||"[object Set]"==t)return!n.size;if(ze(n))return!Vt(n).length;for(var r in n)if(ii.call(n,r))return false;return true},An.isEqual=function(n,t){return Mt(n,t)},An.isEqualWith=function(n,t,r){var e=(r=typeof r=="function"?r:T)?r(n,t):T;return e===T?Mt(n,t,T,r):!!e},An.isError=hu,An.isFinite=function(n){return typeof n=="number"&&zi(n)},An.isFunction=pu,
An.isInteger=_u,An.isLength=vu,An.isMap=lf,An.isMatch=function(n,t){return n===t||$t(n,t,xe(t))},An.isMatchWith=function(n,t,r){return r=typeof r=="function"?r:T,$t(n,t,xe(t),r)},An.isNaN=function(n){return yu(n)&&n!=+n},An.isNative=function(n){if(vo(n))throw new Gu("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");return Ft(n)},An.isNil=function(n){return null==n},An.isNull=function(n){return null===n},An.isNumber=yu,An.isObject=gu,An.isObjectLike=du,An.isPlainObject=bu,An.isRegExp=sf,
An.isSafeInteger=function(n){return _u(n)&&-9007199254740991<=n&&9007199254740991>=n},An.isSet=hf,An.isString=xu,An.isSymbol=ju,An.isTypedArray=pf,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return du(n)&&"[object WeakMap]"==_o(n)},An.isWeakSet=function(n){return du(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Wi.call(n,t)},An.kebabCase=Bf,An.last=qe,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Au(r),u=0>u?Li(e+u,0):Ui(u,e-1)),
t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Uf,An.lt=_f,An.lte=vf,An.max=function(n){return n&&n.length?xt(n,Tu,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,Tu)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,Tu,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=Zu,An.stubFalse=qu,An.stubObject=function(){return{}},An.stubString=function(){
return""},An.stubTrue=function(){return true},An.multiply=tc,An.nth=function(n,t){return n&&n.length?Qt(n,Au(t)):T},An.noConflict=function(){return Fn._===this&&(Fn._=li),this},An.noop=Nu,An.now=Ko,An.pad=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Oi(t),r)+n+ne(Si(t),r))},An.padEnd=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?n+ne(t-e,r):n},An.padStart=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&e<t?ne(t-e,r)+n:n},An.parseInt=function(n,t,r){
return r||null==t?t=0:t&&(t=+t),Di(Ou(n).replace(on,""),t||0)},An.random=function(n,t,r){if(r&&typeof r!="boolean"&&Oe(n,t,r)&&(t=r=T),r===T&&(typeof t=="boolean"?(r=t,t=T):typeof n=="boolean"&&(r=n,n=T)),n===T&&t===T?(n=0,t=1):(n=mu(n),t===T?(t=n,n=0):t=mu(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Mi(),Ui(n+r*(t-n+Dn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=of(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,eo)},An.reduceRight=function(n,t,r){var e=of(n)?s:j,u=3>arguments.length;
return e(n,ye(t,4),r,u,uo)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),or(Ou(n),t)},An.replace=function(){var n=arguments,t=Ou(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++e<u;){var i=null==n?T:n[De(t[e])];i===T&&(e=u,i=r),n=pu(i)?i.call(n):i}return n},An.round=rc,An.runInContext=x,An.sample=function(n){return(of(n)?Qn:cr)(n)},An.size=function(n){if(null==n)return 0;if(lu(n))return xu(n)?D(n):n.length;
var t=_o(n);return"[object Map]"==t||"[object Set]"==t?n.size:Vt(n).length},An.snakeCase=Cf,An.some=function(n,t,r){var e=of(n)?h:pr;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.sortedIndex=function(n,t){return _r(n,t)},An.sortedIndexBy=function(n,t,r){return vr(n,t,ye(r,2))},An.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){var e=_r(n,t);if(e<r&&au(n[e],t))return e}return-1},An.sortedLastIndex=function(n,t){return _r(n,t,true)},An.sortedLastIndexBy=function(n,t,r){return vr(n,t,ye(r,2),true);
},An.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=_r(n,t,true)-1;if(au(n[r],t))return r}return-1},An.startCase=Df,An.startsWith=function(n,t,r){return n=Ou(n),r=null==r?0:pt(Au(r),0,n.length),t=yr(t),n.slice(r,r+t.length)==t},An.subtract=ec,An.sum=function(n){return n&&n.length?m(n,Tu):0},An.sumBy=function(n,t){return n&&n.length?m(n,ye(t,2)):0},An.template=function(n,t,r){var e=An.templateSettings;r&&Oe(n,t,r)&&(t=T),n=Ou(n),t=yf({},t,e,ce),r=yf({},t.imports,e.imports,ce);var u,i,o=zu(r),f=S(r,o),c=0;
r=t.interpolate||jn;var a="__p+='";r=Qu((t.escape||jn).source+"|"+r.source+"|"+(r===Q?pn:jn).source+"|"+(t.evaluate||jn).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(wn,z),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(i?a.replace(P,""):a).replace(Z,"$1").replace(q,"$1;"),
a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=$f(function(){return Hu(o,l+"return "+a).apply(T,f)}),t.source=a,hu(t))throw t;return t},An.times=function(n,t){if(n=Au(n),1>n||9007199254740991<n)return[];var r=4294967295,e=Ui(n,4294967295);for(t=ye(t),n-=4294967295,e=A(e,t);++r<n;)t(r);return e},An.toFinite=mu,An.toInteger=Au,An.toLength=ku,An.toLower=function(n){
return Ou(n).toLowerCase()},An.toNumber=Eu,An.toSafeInteger=function(n){return n?pt(Au(n),-9007199254740991,9007199254740991):0===n?n:0},An.toString=Ou,An.toUpper=function(n){return Ou(n).toUpperCase()},An.trim=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(un,""):n&&(t=yr(t))?(n=M(n),r=M(t),t=I(n,r),r=R(n,r)+1,Or(n,t,r).join("")):n},An.trimEnd=function(n,t,r){return(n=Ou(n))&&(r||t===T)?n.replace(fn,""):n&&(t=yr(t))?(n=M(n),t=R(n,M(t))+1,Or(n,0,t).join("")):n},An.trimStart=function(n,t,r){
return(n=Ou(n))&&(r||t===T)?n.replace(on,""):n&&(t=yr(t))?(n=M(n),t=I(n,M(t)),Or(n,t).join("")):n},An.truncate=function(n,t){var r=30,e="...";if(gu(t))var u="separator"in t?t.separator:u,r="length"in t?Au(t.length):r,e="omission"in t?yr(t.omission):e;n=Ou(n);var i=n.length;if(Rn.test(n))var o=M(n),i=o.length;if(r>=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),sf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Qu(u.source,Ou(_n.exec(u))+"g")),
u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},An.unescape=function(n){return(n=Ou(n))&&G.test(n)?n.replace(V,tt):n},An.uniqueId=function(n){var t=++oi;return Ou(n)+t},An.upperCase=Mf,An.upperFirst=Tf,An.each=Xe,An.eachRight=nu,An.first=Ze,Fu(An,function(){var n={};return mt(An,function(t,r){ii.call(An.prototype,r)||(n[r]=t)}),n}(),{chain:false}),An.VERSION="4.17.5",r("bind bindKey curry curryRight partial partialRight".split(" "),function(n){
An[n].placeholder=An}),r(["drop","take"],function(n,t){Un.prototype[n]=function(r){r=r===T?1:Li(Au(r),0);var e=this.__filtered__&&!t?new Un(this):this.clone();return e.__filtered__?e.__takeCount__=Ui(r,e.__takeCount__):e.__views__.push({size:Ui(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({
iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter(Tu)},Un.prototype.find=function(n){return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n);
},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(cu(ye(n)))},Un.prototype.slice=function(n,t){n=Au(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Au(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295);
},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||of(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({
func:Ye,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ti[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(of(u)?u:[],n)}return this[r](function(r){return t.apply(of(r)?r:[],n)})}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+"";
(Ki[e]||(Ki[e]=[])).push({name:t,func:r})}}),Ki[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n;
},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=of(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c<a;){var l=o[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=Ui(n,f+s);break;case"takeRight":f=Li(f,n-s)}}if(n={start:f,end:n},o=n.start,f=n.end,n=f-o,o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Ui(n,this.__takeCount__),!e||!u&&i==n&&l==n)return wr(t,this.__actions__);e=[];n:for(;n--&&a<l;){for(o+=r,
u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},An.prototype.at=Mo,An.prototype.chain=function(){return Je(this)},An.prototype.commit=function(){return new On(this.value(),this.__chain__)},An.prototype.next=function(){this.__values__===T&&(this.__values__=wu(this.value()));var n=this.__index__>=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof kn;){
var e=$e(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Ye,args:[Ke],thisArg:T}),new On(n,this.__chain__)):this.thru(Ke)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,ji&&(An.prototype[ji]=Qe),
An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Fn._=rt, define(function(){return rt})):Pn?((Pn.exports=rt)._=rt,Nn._=rt):Fn._=rt}).call(this);

430
dist/mapping.fp.js vendored
View File

@@ -1,430 +0,0 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["mapping"] = factory();
else
root["mapping"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
/** Used to map aliases to their real names. */
exports.aliasToReal = {
// Lodash aliases.
'each': 'forEach',
'eachRight': 'forEachRight',
'entries': 'toPairs',
'entriesIn': 'toPairsIn',
'extend': 'assignIn',
'extendAll': 'assignInAll',
'extendAllWith': 'assignInAllWith',
'extendWith': 'assignInWith',
'first': 'head',
// Methods that are curried variants of others.
'conforms': 'conformsTo',
'matches': 'isMatch',
'property': 'get',
// Ramda aliases.
'__': 'placeholder',
'F': 'stubFalse',
'T': 'stubTrue',
'all': 'every',
'allPass': 'overEvery',
'always': 'constant',
'any': 'some',
'anyPass': 'overSome',
'apply': 'spread',
'assoc': 'set',
'assocPath': 'set',
'complement': 'negate',
'compose': 'flowRight',
'contains': 'includes',
'dissoc': 'unset',
'dissocPath': 'unset',
'dropLast': 'dropRight',
'dropLastWhile': 'dropRightWhile',
'equals': 'isEqual',
'identical': 'eq',
'indexBy': 'keyBy',
'init': 'initial',
'invertObj': 'invert',
'juxt': 'over',
'omitAll': 'omit',
'nAry': 'ary',
'path': 'get',
'pathEq': 'matchesProperty',
'pathOr': 'getOr',
'paths': 'at',
'pickAll': 'pick',
'pipe': 'flow',
'pluck': 'map',
'prop': 'get',
'propEq': 'matchesProperty',
'propOr': 'getOr',
'props': 'at',
'symmetricDifference': 'xor',
'symmetricDifferenceBy': 'xorBy',
'symmetricDifferenceWith': 'xorWith',
'takeLast': 'takeRight',
'takeLastWhile': 'takeRightWhile',
'unapply': 'rest',
'unnest': 'flatten',
'useWith': 'overArgs',
'where': 'conformsTo',
'whereEq': 'isMatch',
'zipObj': 'zipObject'
};
/** Used to map ary to method names. */
exports.aryMethod = {
'1': [
'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create',
'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow',
'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll',
'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse',
'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart',
'uniqueId', 'words', 'zipAll'
],
'2': [
'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith',
'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith',
'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN',
'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference',
'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq',
'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex',
'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach',
'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get',
'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection',
'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy',
'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty',
'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit',
'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial',
'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll',
'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove',
'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex',
'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy',
'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight',
'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars',
'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith',
'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject',
'zipObjectDeep'
],
'3': [
'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith',
'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr',
'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith',
'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth',
'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd',
'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight',
'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy',
'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy',
'xorWith', 'zipWith'
],
'4': [
'fill', 'setWith', 'updateWith'
]
};
/** Used to map ary to rearg configs. */
exports.aryRearg = {
'2': [1, 0],
'3': [2, 0, 1],
'4': [3, 2, 0, 1]
};
/** Used to map method names to their iteratee ary. */
exports.iterateeAry = {
'dropRightWhile': 1,
'dropWhile': 1,
'every': 1,
'filter': 1,
'find': 1,
'findFrom': 1,
'findIndex': 1,
'findIndexFrom': 1,
'findKey': 1,
'findLast': 1,
'findLastFrom': 1,
'findLastIndex': 1,
'findLastIndexFrom': 1,
'findLastKey': 1,
'flatMap': 1,
'flatMapDeep': 1,
'flatMapDepth': 1,
'forEach': 1,
'forEachRight': 1,
'forIn': 1,
'forInRight': 1,
'forOwn': 1,
'forOwnRight': 1,
'map': 1,
'mapKeys': 1,
'mapValues': 1,
'partition': 1,
'reduce': 2,
'reduceRight': 2,
'reject': 1,
'remove': 1,
'some': 1,
'takeRightWhile': 1,
'takeWhile': 1,
'times': 1,
'transform': 2
};
/** Used to map method names to iteratee rearg configs. */
exports.iterateeRearg = {
'mapKeys': [1],
'reduceRight': [1, 0]
};
/** Used to map method names to rearg configs. */
exports.methodRearg = {
'assignInAllWith': [1, 0],
'assignInWith': [1, 2, 0],
'assignAllWith': [1, 0],
'assignWith': [1, 2, 0],
'differenceBy': [1, 2, 0],
'differenceWith': [1, 2, 0],
'getOr': [2, 1, 0],
'intersectionBy': [1, 2, 0],
'intersectionWith': [1, 2, 0],
'isEqualWith': [1, 2, 0],
'isMatchWith': [2, 1, 0],
'mergeAllWith': [1, 0],
'mergeWith': [1, 2, 0],
'padChars': [2, 1, 0],
'padCharsEnd': [2, 1, 0],
'padCharsStart': [2, 1, 0],
'pullAllBy': [2, 1, 0],
'pullAllWith': [2, 1, 0],
'rangeStep': [1, 2, 0],
'rangeStepRight': [1, 2, 0],
'setWith': [3, 1, 2, 0],
'sortedIndexBy': [2, 1, 0],
'sortedLastIndexBy': [2, 1, 0],
'unionBy': [1, 2, 0],
'unionWith': [1, 2, 0],
'updateWith': [3, 1, 2, 0],
'xorBy': [1, 2, 0],
'xorWith': [1, 2, 0],
'zipWith': [1, 2, 0]
};
/** Used to map method names to spread configs. */
exports.methodSpread = {
'assignAll': { 'start': 0 },
'assignAllWith': { 'start': 0 },
'assignInAll': { 'start': 0 },
'assignInAllWith': { 'start': 0 },
'defaultsAll': { 'start': 0 },
'defaultsDeepAll': { 'start': 0 },
'invokeArgs': { 'start': 2 },
'invokeArgsMap': { 'start': 2 },
'mergeAll': { 'start': 0 },
'mergeAllWith': { 'start': 0 },
'partial': { 'start': 1 },
'partialRight': { 'start': 1 },
'without': { 'start': 1 },
'zipAll': { 'start': 0 }
};
/** Used to identify methods which mutate arrays or objects. */
exports.mutate = {
'array': {
'fill': true,
'pull': true,
'pullAll': true,
'pullAllBy': true,
'pullAllWith': true,
'pullAt': true,
'remove': true,
'reverse': true
},
'object': {
'assign': true,
'assignAll': true,
'assignAllWith': true,
'assignIn': true,
'assignInAll': true,
'assignInAllWith': true,
'assignInWith': true,
'assignWith': true,
'defaults': true,
'defaultsAll': true,
'defaultsDeep': true,
'defaultsDeepAll': true,
'merge': true,
'mergeAll': true,
'mergeAllWith': true,
'mergeWith': true,
},
'set': {
'set': true,
'setWith': true,
'unset': true,
'update': true,
'updateWith': true
}
};
/** Used to track methods with placeholder support */
exports.placeholder = {
'bind': true,
'bindKey': true,
'curry': true,
'curryRight': true,
'partial': true,
'partialRight': true
};
/** Used to map real names to their aliases. */
exports.realToAlias = (function() {
var hasOwnProperty = Object.prototype.hasOwnProperty,
object = exports.aliasToReal,
result = {};
for (var key in object) {
var value = object[key];
if (hasOwnProperty.call(result, value)) {
result[value].push(key);
} else {
result[value] = [key];
}
}
return result;
}());
/** Used to map method names to other names. */
exports.remap = {
'assignAll': 'assign',
'assignAllWith': 'assignWith',
'assignInAll': 'assignIn',
'assignInAllWith': 'assignInWith',
'curryN': 'curry',
'curryRightN': 'curryRight',
'defaultsAll': 'defaults',
'defaultsDeepAll': 'defaultsDeep',
'findFrom': 'find',
'findIndexFrom': 'findIndex',
'findLastFrom': 'findLast',
'findLastIndexFrom': 'findLastIndex',
'getOr': 'get',
'includesFrom': 'includes',
'indexOfFrom': 'indexOf',
'invokeArgs': 'invoke',
'invokeArgsMap': 'invokeMap',
'lastIndexOfFrom': 'lastIndexOf',
'mergeAll': 'merge',
'mergeAllWith': 'mergeWith',
'padChars': 'pad',
'padCharsEnd': 'padEnd',
'padCharsStart': 'padStart',
'propertyOf': 'get',
'rangeStep': 'range',
'rangeStepRight': 'rangeRight',
'restFrom': 'rest',
'spreadFrom': 'spread',
'trimChars': 'trim',
'trimCharsEnd': 'trimEnd',
'trimCharsStart': 'trimStart',
'zipAll': 'zip'
};
/** Used to track methods that skip fixing their arity. */
exports.skipFixed = {
'castArray': true,
'flow': true,
'flowRight': true,
'iteratee': true,
'mixin': true,
'rearg': true,
'runInContext': true
};
/** Used to track methods that skip rearranging arguments. */
exports.skipRearg = {
'add': true,
'assign': true,
'assignIn': true,
'bind': true,
'bindKey': true,
'concat': true,
'difference': true,
'divide': true,
'eq': true,
'gt': true,
'gte': true,
'isEqual': true,
'lt': true,
'lte': true,
'matchesProperty': true,
'merge': true,
'multiply': true,
'overArgs': true,
'partial': true,
'partialRight': true,
'propertyOf': true,
'random': true,
'range': true,
'rangeRight': true,
'subtract': true,
'zip': true,
'zipObject': true,
'zipObjectDeep': true
};
/***/ })
/******/ ])
});
;

File diff suppressed because it is too large Load Diff

View File

@@ -1,573 +0,0 @@
var mapping = require('./_mapping'),
fallbackHolder = require('./placeholder');
/** Built-in value reference. */
var push = Array.prototype.push;
/**
* Creates a function, with an arity of `n`, that invokes `func` with the
* arguments it receives.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} n The arity of the new function.
* @returns {Function} Returns the new function.
*/
function baseArity(func, n) {
return n == 2
? function(a, b) { return func.apply(undefined, arguments); }
: function(a) { return func.apply(undefined, arguments); };
}
/**
* Creates a function that invokes `func`, with up to `n` arguments, ignoring
* any additional arguments.
*
* @private
* @param {Function} func The function to cap arguments for.
* @param {number} n The arity cap.
* @returns {Function} Returns the new function.
*/
function baseAry(func, n) {
return n == 2
? function(a, b) { return func(a, b); }
: function(a) { return func(a); };
}
/**
* Creates a clone of `array`.
*
* @private
* @param {Array} array The array to clone.
* @returns {Array} Returns the cloned array.
*/
function cloneArray(array) {
var length = array ? array.length : 0,
result = Array(length);
while (length--) {
result[length] = array[length];
}
return result;
}
/**
* Creates a function that clones a given object using the assignment `func`.
*
* @private
* @param {Function} func The assignment function.
* @returns {Function} Returns the new cloner function.
*/
function createCloner(func) {
return function(object) {
return func({}, object);
};
}
/**
* A specialized version of `_.spread` which flattens the spread array into
* the arguments of the invoked `func`.
*
* @private
* @param {Function} func The function to spread arguments over.
* @param {number} start The start position of the spread.
* @returns {Function} Returns the new function.
*/
function flatSpread(func, start) {
return function() {
var length = arguments.length,
lastIndex = length - 1,
args = Array(length);
while (length--) {
args[length] = arguments[length];
}
var array = args[start],
otherArgs = args.slice(0, start);
if (array) {
push.apply(otherArgs, array);
}
if (start != lastIndex) {
push.apply(otherArgs, args.slice(start + 1));
}
return func.apply(this, otherArgs);
};
}
/**
* Creates a function that wraps `func` and uses `cloner` to clone the first
* argument it receives.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} cloner The function to clone arguments.
* @returns {Function} Returns the new immutable function.
*/
function wrapImmutable(func, cloner) {
return function() {
var length = arguments.length;
if (!length) {
return;
}
var args = Array(length);
while (length--) {
args[length] = arguments[length];
}
var result = args[0] = cloner.apply(undefined, args);
func.apply(undefined, args);
return result;
};
}
/**
* The base implementation of `convert` which accepts a `util` object of methods
* required to perform conversions.
*
* @param {Object} util The util object.
* @param {string} name The name of the function to convert.
* @param {Function} func The function to convert.
* @param {Object} [options] The options object.
* @param {boolean} [options.cap=true] Specify capping iteratee arguments.
* @param {boolean} [options.curry=true] Specify currying.
* @param {boolean} [options.fixed=true] Specify fixed arity.
* @param {boolean} [options.immutable=true] Specify immutable operations.
* @param {boolean} [options.rearg=true] Specify rearranging arguments.
* @returns {Function|Object} Returns the converted function or object.
*/
function baseConvert(util, name, func, options) {
var setPlaceholder,
isLib = typeof name == 'function',
isObj = name === Object(name);
if (isObj) {
options = func;
func = name;
name = undefined;
}
if (func == null) {
throw new TypeError;
}
options || (options = {});
var config = {
'cap': 'cap' in options ? options.cap : true,
'curry': 'curry' in options ? options.curry : true,
'fixed': 'fixed' in options ? options.fixed : true,
'immutable': 'immutable' in options ? options.immutable : true,
'rearg': 'rearg' in options ? options.rearg : true
};
var forceCurry = ('curry' in options) && options.curry,
forceFixed = ('fixed' in options) && options.fixed,
forceRearg = ('rearg' in options) && options.rearg,
placeholder = isLib ? func : fallbackHolder,
pristine = isLib ? func.runInContext() : undefined;
var helpers = isLib ? func : {
'ary': util.ary,
'assign': util.assign,
'clone': util.clone,
'curry': util.curry,
'forEach': util.forEach,
'isArray': util.isArray,
'isError': util.isError,
'isFunction': util.isFunction,
'isWeakMap': util.isWeakMap,
'iteratee': util.iteratee,
'keys': util.keys,
'rearg': util.rearg,
'toInteger': util.toInteger,
'toPath': util.toPath
};
var ary = helpers.ary,
assign = helpers.assign,
clone = helpers.clone,
curry = helpers.curry,
each = helpers.forEach,
isArray = helpers.isArray,
isError = helpers.isError,
isFunction = helpers.isFunction,
isWeakMap = helpers.isWeakMap,
keys = helpers.keys,
rearg = helpers.rearg,
toInteger = helpers.toInteger,
toPath = helpers.toPath;
var aryMethodKeys = keys(mapping.aryMethod);
var wrappers = {
'castArray': function(castArray) {
return function() {
var value = arguments[0];
return isArray(value)
? castArray(cloneArray(value))
: castArray.apply(undefined, arguments);
};
},
'iteratee': function(iteratee) {
return function() {
var func = arguments[0],
arity = arguments[1],
result = iteratee(func, arity),
length = result.length;
if (config.cap && typeof arity == 'number') {
arity = arity > 2 ? (arity - 2) : 1;
return (length && length <= arity) ? result : baseAry(result, arity);
}
return result;
};
},
'mixin': function(mixin) {
return function(source) {
var func = this;
if (!isFunction(func)) {
return mixin(func, Object(source));
}
var pairs = [];
each(keys(source), function(key) {
if (isFunction(source[key])) {
pairs.push([key, func.prototype[key]]);
}
});
mixin(func, Object(source));
each(pairs, function(pair) {
var value = pair[1];
if (isFunction(value)) {
func.prototype[pair[0]] = value;
} else {
delete func.prototype[pair[0]];
}
});
return func;
};
},
'nthArg': function(nthArg) {
return function(n) {
var arity = n < 0 ? 1 : (toInteger(n) + 1);
return curry(nthArg(n), arity);
};
},
'rearg': function(rearg) {
return function(func, indexes) {
var arity = indexes ? indexes.length : 0;
return curry(rearg(func, indexes), arity);
};
},
'runInContext': function(runInContext) {
return function(context) {
return baseConvert(util, runInContext(context), options);
};
}
};
/*--------------------------------------------------------------------------*/
/**
* Casts `func` to a function with an arity capped iteratee if needed.
*
* @private
* @param {string} name The name of the function to inspect.
* @param {Function} func The function to inspect.
* @returns {Function} Returns the cast function.
*/
function castCap(name, func) {
if (config.cap) {
var indexes = mapping.iterateeRearg[name];
if (indexes) {
return iterateeRearg(func, indexes);
}
var n = !isLib && mapping.iterateeAry[name];
if (n) {
return iterateeAry(func, n);
}
}
return func;
}
/**
* Casts `func` to a curried function if needed.
*
* @private
* @param {string} name The name of the function to inspect.
* @param {Function} func The function to inspect.
* @param {number} n The arity of `func`.
* @returns {Function} Returns the cast function.
*/
function castCurry(name, func, n) {
return (forceCurry || (config.curry && n > 1))
? curry(func, n)
: func;
}
/**
* Casts `func` to a fixed arity function if needed.
*
* @private
* @param {string} name The name of the function to inspect.
* @param {Function} func The function to inspect.
* @param {number} n The arity cap.
* @returns {Function} Returns the cast function.
*/
function castFixed(name, func, n) {
if (config.fixed && (forceFixed || !mapping.skipFixed[name])) {
var data = mapping.methodSpread[name],
start = data && data.start;
return start === undefined ? ary(func, n) : flatSpread(func, start);
}
return func;
}
/**
* Casts `func` to an rearged function if needed.
*
* @private
* @param {string} name The name of the function to inspect.
* @param {Function} func The function to inspect.
* @param {number} n The arity of `func`.
* @returns {Function} Returns the cast function.
*/
function castRearg(name, func, n) {
return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name]))
? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n])
: func;
}
/**
* Creates a clone of `object` by `path`.
*
* @private
* @param {Object} object The object to clone.
* @param {Array|string} path The path to clone by.
* @returns {Object} Returns the cloned object.
*/
function cloneByPath(object, path) {
path = toPath(path);
var index = -1,
length = path.length,
lastIndex = length - 1,
result = clone(Object(object)),
nested = result;
while (nested != null && ++index < length) {
var key = path[index],
value = nested[key];
if (value != null &&
!(isFunction(value) || isError(value) || isWeakMap(value))) {
nested[key] = clone(index == lastIndex ? value : Object(value));
}
nested = nested[key];
}
return result;
}
/**
* Converts `lodash` to an immutable auto-curried iteratee-first data-last
* version with conversion `options` applied.
*
* @param {Object} [options] The options object. See `baseConvert` for more details.
* @returns {Function} Returns the converted `lodash`.
*/
function convertLib(options) {
return _.runInContext.convert(options)(undefined);
}
/**
* Create a converter function for `func` of `name`.
*
* @param {string} name The name of the function to convert.
* @param {Function} func The function to convert.
* @returns {Function} Returns the new converter function.
*/
function createConverter(name, func) {
var realName = mapping.aliasToReal[name] || name,
methodName = mapping.remap[realName] || realName,
oldOptions = options;
return function(options) {
var newUtil = isLib ? pristine : helpers,
newFunc = isLib ? pristine[methodName] : func,
newOptions = assign(assign({}, oldOptions), options);
return baseConvert(newUtil, realName, newFunc, newOptions);
};
}
/**
* Creates a function that wraps `func` to invoke its iteratee, with up to `n`
* arguments, ignoring any additional arguments.
*
* @private
* @param {Function} func The function to cap iteratee arguments for.
* @param {number} n The arity cap.
* @returns {Function} Returns the new function.
*/
function iterateeAry(func, n) {
return overArg(func, function(func) {
return typeof func == 'function' ? baseAry(func, n) : func;
});
}
/**
* Creates a function that wraps `func` to invoke its iteratee with arguments
* arranged according to the specified `indexes` where the argument value at
* the first index is provided as the first argument, the argument value at
* the second index is provided as the second argument, and so on.
*
* @private
* @param {Function} func The function to rearrange iteratee arguments for.
* @param {number[]} indexes The arranged argument indexes.
* @returns {Function} Returns the new function.
*/
function iterateeRearg(func, indexes) {
return overArg(func, function(func) {
var n = indexes.length;
return baseArity(rearg(baseAry(func, n), indexes), n);
});
}
/**
* Creates a function that invokes `func` with its first argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg(func, transform) {
return function() {
var length = arguments.length;
if (!length) {
return func();
}
var args = Array(length);
while (length--) {
args[length] = arguments[length];
}
var index = config.rearg ? 0 : (length - 1);
args[index] = transform(args[index]);
return func.apply(undefined, args);
};
}
/**
* Creates a function that wraps `func` and applys the conversions
* rules by `name`.
*
* @private
* @param {string} name The name of the function to wrap.
* @param {Function} func The function to wrap.
* @returns {Function} Returns the converted function.
*/
function wrap(name, func) {
var result,
realName = mapping.aliasToReal[name] || name,
wrapped = func,
wrapper = wrappers[realName];
if (wrapper) {
wrapped = wrapper(func);
}
else if (config.immutable) {
if (mapping.mutate.array[realName]) {
wrapped = wrapImmutable(func, cloneArray);
}
else if (mapping.mutate.object[realName]) {
wrapped = wrapImmutable(func, createCloner(func));
}
else if (mapping.mutate.set[realName]) {
wrapped = wrapImmutable(func, cloneByPath);
}
}
each(aryMethodKeys, function(aryKey) {
each(mapping.aryMethod[aryKey], function(otherName) {
if (realName == otherName) {
var data = mapping.methodSpread[realName],
afterRearg = data && data.afterRearg;
result = afterRearg
? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey)
: castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey);
result = castCap(realName, result);
result = castCurry(realName, result, aryKey);
return false;
}
});
return !result;
});
result || (result = wrapped);
if (result == func) {
result = forceCurry ? curry(result, 1) : function() {
return func.apply(this, arguments);
};
}
result.convert = createConverter(realName, func);
if (mapping.placeholder[realName]) {
setPlaceholder = true;
result.placeholder = func.placeholder = placeholder;
}
return result;
}
/*--------------------------------------------------------------------------*/
if (!isObj) {
return wrap(name, func);
}
var _ = func;
// Convert methods by ary cap.
var pairs = [];
each(aryMethodKeys, function(aryKey) {
each(mapping.aryMethod[aryKey], function(key) {
var func = _[mapping.remap[key] || key];
if (func) {
pairs.push([key, wrap(key, func)]);
}
});
});
// Convert remaining methods.
each(keys(_), function(key) {
var func = _[key];
if (typeof func == 'function') {
var length = pairs.length;
while (length--) {
if (pairs[length][0] == key) {
return;
}
}
func.convert = createConverter(key, func);
pairs.push([key, func]);
}
});
// Assign to `_` leaving `_.prototype` unchanged to allow chaining.
each(pairs, function(pair) {
_[pair[0]] = pair[1];
});
_.convert = convertLib;
if (setPlaceholder) {
_.placeholder = placeholder;
}
// Assign aliases.
each(keys(_), function(key) {
each(mapping.realToAlias[key] || [], function(alias) {
_[alias] = _[key];
});
});
return _;
}
module.exports = baseConvert;

View File

@@ -1,18 +0,0 @@
var baseConvert = require('./_baseConvert');
/**
* Converts `lodash` to an immutable auto-curried iteratee-first data-last
* version with conversion `options` applied.
*
* @param {Function} lodash The lodash function to convert.
* @param {Object} [options] The options object. See `baseConvert` for more details.
* @returns {Function} Returns the converted `lodash`.
*/
function browserConvert(lodash, options) {
return baseConvert(lodash, lodash, options);
}
if (typeof _ == 'function' && typeof _.runInContext == 'function') {
_ = browserConvert(_.runInContext());
}
module.exports = browserConvert;

View File

@@ -1,368 +0,0 @@
/** Used to map aliases to their real names. */
exports.aliasToReal = {
// Lodash aliases.
'each': 'forEach',
'eachRight': 'forEachRight',
'entries': 'toPairs',
'entriesIn': 'toPairsIn',
'extend': 'assignIn',
'extendAll': 'assignInAll',
'extendAllWith': 'assignInAllWith',
'extendWith': 'assignInWith',
'first': 'head',
// Methods that are curried variants of others.
'conforms': 'conformsTo',
'matches': 'isMatch',
'property': 'get',
// Ramda aliases.
'__': 'placeholder',
'F': 'stubFalse',
'T': 'stubTrue',
'all': 'every',
'allPass': 'overEvery',
'always': 'constant',
'any': 'some',
'anyPass': 'overSome',
'apply': 'spread',
'assoc': 'set',
'assocPath': 'set',
'complement': 'negate',
'compose': 'flowRight',
'contains': 'includes',
'dissoc': 'unset',
'dissocPath': 'unset',
'dropLast': 'dropRight',
'dropLastWhile': 'dropRightWhile',
'equals': 'isEqual',
'identical': 'eq',
'indexBy': 'keyBy',
'init': 'initial',
'invertObj': 'invert',
'juxt': 'over',
'omitAll': 'omit',
'nAry': 'ary',
'path': 'get',
'pathEq': 'matchesProperty',
'pathOr': 'getOr',
'paths': 'at',
'pickAll': 'pick',
'pipe': 'flow',
'pluck': 'map',
'prop': 'get',
'propEq': 'matchesProperty',
'propOr': 'getOr',
'props': 'at',
'symmetricDifference': 'xor',
'symmetricDifferenceBy': 'xorBy',
'symmetricDifferenceWith': 'xorWith',
'takeLast': 'takeRight',
'takeLastWhile': 'takeRightWhile',
'unapply': 'rest',
'unnest': 'flatten',
'useWith': 'overArgs',
'where': 'conformsTo',
'whereEq': 'isMatch',
'zipObj': 'zipObject'
};
/** Used to map ary to method names. */
exports.aryMethod = {
'1': [
'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create',
'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow',
'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll',
'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse',
'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart',
'uniqueId', 'words', 'zipAll'
],
'2': [
'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith',
'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith',
'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN',
'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference',
'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq',
'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex',
'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach',
'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get',
'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection',
'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy',
'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty',
'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit',
'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial',
'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll',
'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove',
'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex',
'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy',
'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight',
'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars',
'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith',
'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject',
'zipObjectDeep'
],
'3': [
'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith',
'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr',
'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith',
'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth',
'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd',
'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight',
'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy',
'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy',
'xorWith', 'zipWith'
],
'4': [
'fill', 'setWith', 'updateWith'
]
};
/** Used to map ary to rearg configs. */
exports.aryRearg = {
'2': [1, 0],
'3': [2, 0, 1],
'4': [3, 2, 0, 1]
};
/** Used to map method names to their iteratee ary. */
exports.iterateeAry = {
'dropRightWhile': 1,
'dropWhile': 1,
'every': 1,
'filter': 1,
'find': 1,
'findFrom': 1,
'findIndex': 1,
'findIndexFrom': 1,
'findKey': 1,
'findLast': 1,
'findLastFrom': 1,
'findLastIndex': 1,
'findLastIndexFrom': 1,
'findLastKey': 1,
'flatMap': 1,
'flatMapDeep': 1,
'flatMapDepth': 1,
'forEach': 1,
'forEachRight': 1,
'forIn': 1,
'forInRight': 1,
'forOwn': 1,
'forOwnRight': 1,
'map': 1,
'mapKeys': 1,
'mapValues': 1,
'partition': 1,
'reduce': 2,
'reduceRight': 2,
'reject': 1,
'remove': 1,
'some': 1,
'takeRightWhile': 1,
'takeWhile': 1,
'times': 1,
'transform': 2
};
/** Used to map method names to iteratee rearg configs. */
exports.iterateeRearg = {
'mapKeys': [1],
'reduceRight': [1, 0]
};
/** Used to map method names to rearg configs. */
exports.methodRearg = {
'assignInAllWith': [1, 0],
'assignInWith': [1, 2, 0],
'assignAllWith': [1, 0],
'assignWith': [1, 2, 0],
'differenceBy': [1, 2, 0],
'differenceWith': [1, 2, 0],
'getOr': [2, 1, 0],
'intersectionBy': [1, 2, 0],
'intersectionWith': [1, 2, 0],
'isEqualWith': [1, 2, 0],
'isMatchWith': [2, 1, 0],
'mergeAllWith': [1, 0],
'mergeWith': [1, 2, 0],
'padChars': [2, 1, 0],
'padCharsEnd': [2, 1, 0],
'padCharsStart': [2, 1, 0],
'pullAllBy': [2, 1, 0],
'pullAllWith': [2, 1, 0],
'rangeStep': [1, 2, 0],
'rangeStepRight': [1, 2, 0],
'setWith': [3, 1, 2, 0],
'sortedIndexBy': [2, 1, 0],
'sortedLastIndexBy': [2, 1, 0],
'unionBy': [1, 2, 0],
'unionWith': [1, 2, 0],
'updateWith': [3, 1, 2, 0],
'xorBy': [1, 2, 0],
'xorWith': [1, 2, 0],
'zipWith': [1, 2, 0]
};
/** Used to map method names to spread configs. */
exports.methodSpread = {
'assignAll': { 'start': 0 },
'assignAllWith': { 'start': 0 },
'assignInAll': { 'start': 0 },
'assignInAllWith': { 'start': 0 },
'defaultsAll': { 'start': 0 },
'defaultsDeepAll': { 'start': 0 },
'invokeArgs': { 'start': 2 },
'invokeArgsMap': { 'start': 2 },
'mergeAll': { 'start': 0 },
'mergeAllWith': { 'start': 0 },
'partial': { 'start': 1 },
'partialRight': { 'start': 1 },
'without': { 'start': 1 },
'zipAll': { 'start': 0 }
};
/** Used to identify methods which mutate arrays or objects. */
exports.mutate = {
'array': {
'fill': true,
'pull': true,
'pullAll': true,
'pullAllBy': true,
'pullAllWith': true,
'pullAt': true,
'remove': true,
'reverse': true
},
'object': {
'assign': true,
'assignAll': true,
'assignAllWith': true,
'assignIn': true,
'assignInAll': true,
'assignInAllWith': true,
'assignInWith': true,
'assignWith': true,
'defaults': true,
'defaultsAll': true,
'defaultsDeep': true,
'defaultsDeepAll': true,
'merge': true,
'mergeAll': true,
'mergeAllWith': true,
'mergeWith': true,
},
'set': {
'set': true,
'setWith': true,
'unset': true,
'update': true,
'updateWith': true
}
};
/** Used to track methods with placeholder support */
exports.placeholder = {
'bind': true,
'bindKey': true,
'curry': true,
'curryRight': true,
'partial': true,
'partialRight': true
};
/** Used to map real names to their aliases. */
exports.realToAlias = (function() {
var hasOwnProperty = Object.prototype.hasOwnProperty,
object = exports.aliasToReal,
result = {};
for (var key in object) {
var value = object[key];
if (hasOwnProperty.call(result, value)) {
result[value].push(key);
} else {
result[value] = [key];
}
}
return result;
}());
/** Used to map method names to other names. */
exports.remap = {
'assignAll': 'assign',
'assignAllWith': 'assignWith',
'assignInAll': 'assignIn',
'assignInAllWith': 'assignInWith',
'curryN': 'curry',
'curryRightN': 'curryRight',
'defaultsAll': 'defaults',
'defaultsDeepAll': 'defaultsDeep',
'findFrom': 'find',
'findIndexFrom': 'findIndex',
'findLastFrom': 'findLast',
'findLastIndexFrom': 'findLastIndex',
'getOr': 'get',
'includesFrom': 'includes',
'indexOfFrom': 'indexOf',
'invokeArgs': 'invoke',
'invokeArgsMap': 'invokeMap',
'lastIndexOfFrom': 'lastIndexOf',
'mergeAll': 'merge',
'mergeAllWith': 'mergeWith',
'padChars': 'pad',
'padCharsEnd': 'padEnd',
'padCharsStart': 'padStart',
'propertyOf': 'get',
'rangeStep': 'range',
'rangeStepRight': 'rangeRight',
'restFrom': 'rest',
'spreadFrom': 'spread',
'trimChars': 'trim',
'trimCharsEnd': 'trimEnd',
'trimCharsStart': 'trimStart',
'zipAll': 'zip'
};
/** Used to track methods that skip fixing their arity. */
exports.skipFixed = {
'castArray': true,
'flow': true,
'flowRight': true,
'iteratee': true,
'mixin': true,
'rearg': true,
'runInContext': true
};
/** Used to track methods that skip rearranging arguments. */
exports.skipRearg = {
'add': true,
'assign': true,
'assignIn': true,
'bind': true,
'bindKey': true,
'concat': true,
'difference': true,
'divide': true,
'eq': true,
'gt': true,
'gte': true,
'isEqual': true,
'lt': true,
'lte': true,
'matchesProperty': true,
'merge': true,
'multiply': true,
'overArgs': true,
'partial': true,
'partialRight': true,
'propertyOf': true,
'random': true,
'range': true,
'rangeRight': true,
'subtract': true,
'zip': true,
'zipObject': true,
'zipObjectDeep': true
};

View File

@@ -1,6 +0,0 @@
/**
* The default argument placeholder value for methods.
*
* @type {Object}
*/
module.exports = {};

View File

@@ -1,71 +0,0 @@
'use strict';
const _ = require('lodash');
const fs = require('fs-extra');
const glob = require('glob');
const path = require('path');
const minify = require('../common/minify.js');
/*----------------------------------------------------------------------------*/
/**
* Creates a [fs.copy](https://github.com/jprichardson/node-fs-extra#copy)
* function with `srcPath` and `destPath` partially applied.
*
* @memberOf file
* @param {string} srcPath The path of the file to copy.
* @param {string} destPath The path to copy the file to.
* @returns {Function} Returns the partially applied function.
*/
function copy(srcPath, destPath) {
return _.partial(fs.copy, srcPath, destPath);
}
/**
* Creates an object of base name and compiled template pairs that match `pattern`.
*
* @memberOf file
* @param {string} pattern The glob pattern to be match.
* @returns {Object} Returns the object of compiled templates.
*/
function globTemplate(pattern) {
return _.transform(glob.sync(pattern), (result, filePath) => {
const key = path.basename(filePath, path.extname(filePath));
result[key] = _.template(fs.readFileSync(filePath, 'utf8'));
}, {});
}
/**
* Creates a `minify` function with `srcPath` and `destPath` partially applied.
*
* @memberOf file
* @param {string} srcPath The path of the file to minify.
* @param {string} destPath The path to write the file to.
* @returns {Function} Returns the partially applied function.
*/
function min(srcPath, destPath) {
return _.partial(minify, srcPath, destPath);
}
/**
* Creates a [fs.writeFile](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback)
* function with `filePath` and `data` partially applied.
*
* @memberOf file
* @param {string} destPath The path to write the file to.
* @param {string} data The data to write to the file.
* @returns {Function} Returns the partially applied function.
*/
function write(destPath, data) {
return _.partial(fs.writeFile, destPath, data);
}
/*----------------------------------------------------------------------------*/
module.exports = {
copy,
globTemplate,
min,
write
};

View File

@@ -1,9 +0,0 @@
'use strict';
const _mapping = require('../../fp/_mapping');
const util = require('./util');
const Hash = util.Hash;
/*----------------------------------------------------------------------------*/
module.exports = new Hash(_mapping);

View File

@@ -1,39 +0,0 @@
'use strict';
const _ = require('lodash');
const fs = require('fs-extra');
const uglify = require('uglify-js');
const uglifyOptions = require('./uglify.options');
/*----------------------------------------------------------------------------*/
/**
* Asynchronously minifies the file at `srcPath`, writes it to `destPath`, and
* invokes `callback` upon completion. The callback is invoked with one argument:
* (error).
*
* If unspecified, `destPath` is `srcPath` with an extension of `.min.js`.
* (e.g. the `destPath` of `path/to/foo.js` would be `path/to/foo.min.js`)
*
* @param {string} srcPath The path of the file to minify.
* @param {string} [destPath] The path to write the file to.
* @param {Function} callback The function invoked upon completion.
* @param {Object} [option] The UglifyJS options object.
*/
function minify(srcPath, destPath, callback, options) {
if (_.isFunction(destPath)) {
if (_.isObject(callback)) {
options = callback;
}
callback = destPath;
destPath = undefined;
}
if (!destPath) {
destPath = srcPath.replace(/(?=\.js$)/, '.min');
}
const output = uglify.minify(srcPath, _.defaults(options || {}, uglifyOptions));
fs.writeFile(destPath, output.code, 'utf-8', callback);
}
module.exports = minify;

View File

@@ -1,22 +0,0 @@
'use strict';
/**
* The UglifyJS options object for
* [compress](https://github.com/mishoo/UglifyJS2#compressor-options),
* [mangle](https://github.com/mishoo/UglifyJS2#mangler-options), and
* [output](https://github.com/mishoo/UglifyJS2#beautifier-options) options.
*/
module.exports = {
'compress': {
'collapse_vars': true,
'negate_iife': false,
'pure_getters': true,
'unsafe': true,
'warnings': false
},
'output': {
'ascii_only': true,
'comments': /@license/,
'max_line_len': 500
}
};

View File

@@ -1,40 +0,0 @@
'use strict';
const _ = require('lodash');
/*----------------------------------------------------------------------------*/
/**
* Creates a hash object. If a `properties` object is provided, its own
* enumerable properties are assigned to the created hash.
*
* @memberOf util
* @param {Object} [properties] The properties to assign to the hash.
* @returns {Object} Returns the new hash object.
*/
function Hash(properties) {
return _.transform(properties, (result, value, key) => {
result[key] = (_.isPlainObject(value) && !(value instanceof Hash))
? new Hash(value)
: value;
}, this);
}
Hash.prototype = Object.create(null);
/**
* This method throws any error it receives.
*
* @memberOf util
* @param {Object} [error] The error object.
*/
function pitch(error) {
if (error != null) {
throw error;
}
}
module.exports = {
Hash,
pitch
};

View File

@@ -1,56 +0,0 @@
'use strict';
const _ = require('lodash');
const async = require('async');
const path = require('path');
const webpack = require('webpack');
const file = require('../common/file');
const util = require('../common/util');
const basePath = path.join(__dirname, '..', '..');
const distPath = path.join(basePath, 'dist');
const fpPath = path.join(basePath, 'fp');
const filename = 'lodash.fp.js';
const fpConfig = {
'entry': path.join(fpPath, '_convertBrowser.js'),
'output': {
'path': distPath,
'filename': filename,
'library': 'fp',
'libraryTarget': 'umd'
},
'plugins': [
new webpack.optimize.OccurenceOrderPlugin,
new webpack.optimize.DedupePlugin
]
};
const mappingConfig = {
'entry': path.join(fpPath, '_mapping.js'),
'output': {
'path': distPath,
'filename': 'mapping.fp.js',
'library': 'mapping',
'libraryTarget': 'umd'
}
};
/*----------------------------------------------------------------------------*/
/**
* Creates browser builds of the FP converter and mappings at the `target` path.
*
* @private
* @param {string} target The output directory path.
*/
function build() {
async.series([
_.partial(webpack, mappingConfig),
_.partial(webpack, fpConfig),
file.min(path.join(distPath, filename))
], util.pitch);
}
build();

View File

@@ -1,78 +0,0 @@
'use strict';
const _ = require('lodash');
const fs = require('fs-extra');
const path = require('path');
const file = require('../common/file');
const mapping = require('../common/mapping');
const util = require('../common/util');
const templatePath = path.join(__dirname, 'template/doc');
const template = file.globTemplate(path.join(templatePath, '*.jst'));
const argNames = ['a', 'b', 'c', 'd'];
const templateData = {
mapping,
toArgOrder,
toFuncList
};
/**
* Converts arranged argument `indexes` into a named argument string
* representation of their order.
*
* @private
* @param {number[]} indexes The arranged argument indexes.
* @returns {string} Returns the named argument string.
*/
function toArgOrder(indexes) {
const reordered = [];
_.each(indexes, (newIndex, index) => {
reordered[newIndex] = argNames[index];
});
return '`(' + reordered.join(', ') + ')`';
}
/**
* Converts `funcNames` into a chunked list string representation.
*
* @private
* @param {string[]} funcNames The function names.
* @returns {string} Returns the function list string.
*/
function toFuncList(funcNames) {
let chunks = _.chunk(funcNames.slice().sort(), 5);
let lastChunk = _.last(chunks);
const lastName = lastChunk ? lastChunk.pop() : undefined;
chunks = _.reject(chunks, _.isEmpty);
lastChunk = _.last(chunks);
let result = '`' + _.map(chunks, chunk => chunk.join('`, `') + '`').join(',\n`');
if (lastName == null) {
return result;
}
if (_.size(chunks) > 1 || _.size(lastChunk) > 1) {
result += ',';
}
result += ' &';
result += _.size(lastChunk) < 5 ? ' ' : '\n';
return result + '`' + lastName + '`';
}
/*----------------------------------------------------------------------------*/
/**
* Creates the FP-Guide wiki at the `target` path.
*
* @private
* @param {string} target The output file path.
*/
function build(target) {
target = path.resolve(target);
fs.writeFile(target, template.wiki(templateData), util.pitch);
}
build(_.last(process.argv));

View File

@@ -1,150 +0,0 @@
'use strict';
const _ = require('lodash');
const async = require('async');
const glob = require('glob');
const path = require('path');
const file = require('../common/file');
const mapping = require('../common/mapping');
const util = require('../common/util');
const templatePath = path.join(__dirname, 'template/modules');
const template = file.globTemplate(path.join(templatePath, '*.jst'));
const aryMethods = _.union(
mapping.aryMethod[1],
mapping.aryMethod[2],
mapping.aryMethod[3],
mapping.aryMethod[4]
);
const categories = [
'array',
'collection',
'date',
'function',
'lang',
'math',
'number',
'object',
'seq',
'string',
'util'
];
const ignored = [
'_*.js',
'core.js',
'core.min.js',
'fp.js',
'index.js',
'lodash.js',
'lodash.min.js'
];
/**
* Checks if `name` is a method alias.
*
* @private
* @param {string} name The name to check.
* @returns {boolean} Returns `true` if `name` is a method alias, else `false`.
*/
function isAlias(name) {
return _.has(mapping.aliasToReal, name);
}
/**
* Checks if `name` is a category name.
*
* @private
* @param {string} name The name to check.
* @returns {boolean} Returns `true` if `name` is a category name, else `false`.
*/
function isCategory(name) {
return _.includes(categories, name);
}
/**
* Checks if `name` belongs to a method that's passed thru and not wrapped.
*
* @private
* @param {string} name The name to check.
* @returns {boolean} Returns `true` if `name` is of a pass thru method,
* else `false`.
*/
function isThru(name) {
return !_.includes(aryMethods, name);
}
/**
* Gets metadata for `func`.
*
* @private
* @param {Function} func The function to query.
* @returns {*} Returns the metadata for `func`.
*/
function getTemplate(moduleName) {
const data = {
'name': _.get(mapping.aliasToReal, moduleName, moduleName),
'mapping': mapping
};
if (isAlias(moduleName)) {
return template.alias(data);
}
if (isCategory(moduleName)) {
return template.category(data);
}
if (isThru(moduleName)) {
return template.thru(data);
}
return template.module(data);
}
/*----------------------------------------------------------------------------*/
/**
* Creates FP modules at the `target` path.
*
* @private
* @param {string} target The output directory path.
*/
function build(target) {
target = path.resolve(target);
const fpPath = path.join(target, 'fp');
// Glob existing lodash module paths.
const modulePaths = glob.sync(path.join(target, '*.js'), {
'nodir': true,
'ignore': ignored.map(filename => {
return path.join(target, filename);
})
});
// Add FP alias and remapped module paths.
_.each([mapping.aliasToReal, mapping.remap], data => {
_.forOwn(data, (realName, alias) => {
const modulePath = path.join(target, alias + '.js');
if (!_.includes(modulePaths, modulePath)) {
modulePaths.push(modulePath);
}
});
});
const actions = modulePaths.map(modulePath => {
const moduleName = path.basename(modulePath, '.js');
return file.write(path.join(fpPath, moduleName + '.js'), getTemplate(moduleName));
});
actions.unshift(file.copy(path.join(__dirname, '../../fp'), fpPath));
actions.push(file.write(path.join(fpPath, '_falseOptions.js'), template._falseOptions()));
actions.push(file.write(path.join(fpPath, '_util.js'), template._util()));
actions.push(file.write(path.join(target, 'fp.js'), template.fp()));
actions.push(file.write(path.join(fpPath, 'convert.js'), template.convert()));
async.series(actions, util.pitch);
}
build(_.last(process.argv));

View File

@@ -1,228 +0,0 @@
## lodash/fp
The `lodash/fp` module promotes a more
[functional programming](https://en.wikipedia.org/wiki/Functional_programming)
(FP) friendly style by exporting an instance of `lodash` with its methods wrapped
to produce immutable auto-curried iteratee-first data-last methods.
## Installation
In a browser:
```html
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
<script>
// Loading `lodash.fp.js` converts `_` to its fp variant.
_.defaults({ 'a': 2, 'b': 2 })({ 'a': 1 });
// ➜ { 'a': 1, 'b': 2 }
// Use `noConflict` to restore the pre-fp variant.
var fp = _.noConflict();
_.defaults({ 'a': 1 }, { 'a': 2, 'b': 2 });
// ➜ { 'a': 1, 'b': 2 }
fp.defaults({ 'a': 2, 'b': 2 })({ 'a': 1 });
// ➜ { 'a': 1, 'b': 2 }
</script>
```
In Node.js:
```js
// Load the fp build.
var fp = require('lodash/fp');
// Load a method category.
var object = require('lodash/fp/object');
// Load a single method for smaller builds with browserify/rollup/webpack.
var extend = require('lodash/fp/extend');
```
## Mapping
Immutable auto-curried iteratee-first data-last methods sound great, but what
does that really mean for each method? Below is a breakdown of the mapping used
to convert each method.
#### Capped Iteratee Arguments
Iteratee arguments are capped to avoid gotchas with variadic iteratees.
```js
// The `lodash/map` iteratee receives three arguments:
// (value, index|key, collection)
_.map(['6', '8', '10'], parseInt);
// ➜ [6, NaN, 2]
// The `lodash/fp/map` iteratee is capped at one argument:
// (value)
fp.map(parseInt)(['6', '8', '10']);
// ➜ [6, 8, 10]
```
Methods that cap iteratees to one argument:<br>
<%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 1)))) %>
Methods that cap iteratees to two arguments:<br>
<%= toFuncList(_.keys(_.pickBy(mapping.iterateeAry, _.partial(_.eq, _, 2)))) %>
The iteratee of `mapKeys` is capped to one argument: `(key)`
#### Fixed Arity
Methods have fixed arities to support auto-currying.
```js
// `lodash/padStart` accepts an optional `chars` param.
_.padStart('a', 3, '-')
// ➜ '--a'
// `lodash/fp/padStart` does not.
fp.padStart(3)('a');
// ➜ ' a'
fp.padCharsStart('-')(3)('a');
// ➜ '--a'
```
Methods with a fixed arity of one:<br>
<%= toFuncList(_.difference(mapping.aryMethod[1], _.keys(mapping.skipFixed))) %>
Methods with a fixed arity of two:<br>
<%= toFuncList(_.difference(mapping.aryMethod[2], _.keys(mapping.skipFixed))) %>
Methods with a fixed arity of three:<br>
<%= toFuncList(_.difference(mapping.aryMethod[3], _.keys(mapping.skipFixed))) %>
Methods with a fixed arity of four:<br>
<%= toFuncList(_.difference(mapping.aryMethod[4], _.keys(mapping.skipFixed))) %>
#### Rearranged Arguments
Method arguments are rearranged to make composition easier.
```js
// `lodash/filter` is data-first iteratee-last:
// (collection, iteratee)
var compact = _.partial(_.filter, _, Boolean);
compact(['a', null, 'c']);
// ➜ ['a', 'c']
// `lodash/fp/filter` is iteratee-first data-last:
// (iteratee, collection)
var compact = fp.filter(Boolean);
compact(['a', null, 'c']);
// ➜ ['a', 'c']
```
##### Most methods follow these rules
A fixed arity of two has an argument order of:<br>
<%= toArgOrder(mapping.aryRearg[2]) %>
A fixed arity of three has an argument order of:<br>
<%= toArgOrder(mapping.aryRearg[3]) %>
A fixed arity of four has an argument order of:<br>
<%= toArgOrder(mapping.aryRearg[4]) %>
##### Exceptions to the rules
Methods that accept an array as their last or only argument:<br>
<%= toFuncList(_.keys(mapping.methodSpread)) %>
Methods with unchanged argument orders:<br>
<%= toFuncList(_.keys(mapping.skipRearg)) %>
Methods with custom argument orders:<br>
<%= _.map(_.keys(mapping.methodRearg), methodName => {
const orders = mapping.methodRearg[methodName];
return ' * `_.' + methodName + '` has an order of ' + toArgOrder(orders);
}).join('\n') %>
The iteratee of `reduceRight` has an argument order of: `(b, a)`
#### New Methods
Not all variadic methods have corresponding new method variants. Feel free to
[request](https://github.com/lodash/lodash/blob/master/.github/CONTRIBUTING.md#feature-requests)
any additions.
Methods created to accommodate Lodashs variadic methods:<br>
<%= toFuncList(_.keys(mapping.remap)) %>
#### Aliases
There are <%= _.size(mapping.aliasToReal) %> method aliases:<br>
<%= _.map(_.keys(mapping.aliasToReal).sort(), alias => {
const realName = mapping.aliasToReal[alias];
return ' * `_.' + alias + '` is an alias of `_.' + realName + '`';
}).join('\n') %>
## Placeholders
The placeholder argument, which defaults to `_`, may be used to fill in method
arguments in a different order. Placeholders are filled by the first available
arguments of the curried returned function.
```js
// The equivalent of `2 > 5`.
_.gt(2)(5);
// ➜ false
// The equivalent of `_.gt(5, 2)` or `5 > 2`.
_.gt(_, 2)(5);
// ➜ true
```
## Chaining
The `lodash/fp` module **does not** convert chain sequence methods. See
[Izaak Schroeders article](https://medium.com/making-internets/why-using-chain-is-a-mistake-9bc1f80d51ba)
on using functional composition as an alternative to method chaining.
## Convert
Although `lodash/fp` & its method modules come pre-converted, there are times
when you may want to customize the conversion. Thats when the `convert` method
comes in handy.
```js
// Every option is `true` by default.
var _fp = fp.convert({
// Specify capping iteratee arguments.
'cap': true,
// Specify currying.
'curry': true,
// Specify fixed arity.
'fixed': true,
// Specify immutable operations.
'immutable': true,
// Specify rearranging arguments.
'rearg': true
});
// The `convert` method is available on each method too.
var mapValuesWithKey = fp.mapValues.convert({ 'cap': false });
// Heres an example of disabling iteratee argument caps to access the `key` param.
mapValuesWithKey(function(value, key) {
return key == 'a' ? -1 : value;
})({ 'a': 1, 'b': 1 });
// => { 'a': -1, 'b': 1 }
```
Manual conversions are also possible with the `convert` module.
```js
var convert = require('lodash/fp/convert');
// Convert by name.
var assign = convert('assign', require('lodash.assign'));
// Convert by object.
var fp = convert({
'assign': require('lodash.assign'),
'chunk': require('lodash.chunk')
});
// Convert by `lodash` instance.
var fp = convert(lodash.runInContext());
```
## Tooling
Use [eslint-plugin-lodash-fp](https://www.npmjs.com/package/eslint-plugin-lodash-fp)
to help use `lodash/fp` more efficiently.

View File

@@ -1,7 +0,0 @@
module.exports = {
'cap': false,
'curry': false,
'fixed': false,
'immutable': false,
'rearg': false
};

View File

@@ -1,16 +0,0 @@
module.exports = {
'ary': require('../ary'),
'assign': require('../_baseAssign'),
'clone': require('../clone'),
'curry': require('../curry'),
'forEach': require('../_arrayEach'),
'isArray': require('../isArray'),
'isError': require('../isError'),
'isFunction': require('../isFunction'),
'isWeakMap': require('../isWeakMap'),
'iteratee': require('../iteratee'),
'keys': require('../_baseKeys'),
'rearg': require('../rearg'),
'toInteger': require('../toInteger'),
'toPath': require('../toPath')
};

View File

@@ -1 +0,0 @@
module.exports = require('./<%= name %>');

View File

@@ -1,2 +0,0 @@
var convert = require('./convert');
module.exports = convert(require('../<%= name %>'));

View File

@@ -1,18 +0,0 @@
var baseConvert = require('./_baseConvert'),
util = require('./_util');
/**
* Converts `func` of `name` to an immutable auto-curried iteratee-first data-last
* version with conversion `options` applied. If `name` is an object its methods
* will be converted.
*
* @param {string} name The name of the function to wrap.
* @param {Function} [func] The function to wrap.
* @param {Object} [options] The options object. See `baseConvert` for more details.
* @returns {Function|Object} Returns the converted function or object.
*/
function convert(name, func, options) {
return baseConvert(util, name, func, options);
}
module.exports = convert;

View File

@@ -1,2 +0,0 @@
var _ = require('./lodash.min').runInContext();
module.exports = require('./fp/_baseConvert')(_, _);

View File

@@ -1,5 +0,0 @@
var convert = require('./convert'),
func = convert('<%= name %>', require('../<%= _.get(mapping.remap, name, name) %>'));
func.placeholder = require('./placeholder');
module.exports = func;

View File

@@ -1,5 +0,0 @@
var convert = require('./convert'),
func = convert('<%= name %>', require('../<%= _.get(mapping.remap, name, name) %>'), require('./_falseOptions'));
func.placeholder = require('./placeholder');
module.exports = func;

View File

@@ -1,31 +0,0 @@
'use strict';
const async = require('async');
const path = require('path');
const file = require('../common/file');
const util = require('../common/util');
const basePath = path.join(__dirname, '..', '..');
const distPath = path.join(basePath, 'dist');
const filename = 'lodash.js';
const baseLodash = path.join(basePath, filename);
const distLodash = path.join(distPath, filename);
/*----------------------------------------------------------------------------*/
/**
* Creates browser builds of Lodash at the `target` path.
*
* @private
* @param {string} target The output directory path.
*/
function build() {
async.series([
file.copy(baseLodash, distLodash),
file.min(distLodash)
], util.pitch);
}
build();

View File

@@ -1,83 +0,0 @@
'use strict';
const _ = require('lodash');
const docdown = require('docdown');
const fs = require('fs-extra');
const path = require('path');
const util = require('../common/util');
const basePath = path.join(__dirname, '..', '..');
const docPath = path.join(basePath, 'doc');
const readmePath = path.join(docPath, 'README.md');
const pkg = require('../../package.json');
const version = pkg.version;
const config = {
'base': {
'path': path.join(basePath, 'lodash.js'),
'title': `<a href="https://lodash.com/">lodash</a> <span>v${ version }</span>`,
'toc': 'categories',
'url': `https://github.com/lodash/lodash/blob/${ version }/lodash.js`
},
'github': {
'style': 'github',
'sublinks': [npmLink('&#x24C3;', 'See the npm package')]
},
'site': {
'entryLink': '<a href="${entryHref}" class="fa fa-link"></a>',
'sourceLink': '[source](${sourceHref})',
'tocHref': '',
'tocLink': '',
'sublinks': [npmLink('npm package')]
}
};
/**
* Composes a npm link from `text` and optional `title`.
*
* @private
* @param {string} text The link text.
* @param {string} [title] The link title.
* @returns {string} Returns the composed npm link.
*/
function npmLink(text, title) {
return (
'<% if (name == "templateSettings" || !/^(?:methods|properties|seq)$/i.test(category)) {' +
'print(' +
'"[' + text + '](https://www.npmjs.com/package/lodash." + name.toLowerCase() + ' +
'"' + (title == null ? '' : ' \\"' + title + '\\"') + ')"' +
');' +
'} %>'
);
}
/**
* Post-process `markdown` to make adjustments.
*
* @private
* @param {string} markdown The markdown to process.
* @returns {string} Returns the processed markdown.
*/
function postprocess(markdown) {
// Wrap symbol property identifiers in brackets.
return markdown.replace(/\.(Symbol\.(?:[a-z]+[A-Z]?)+)/g, '[$1]');
}
/*----------------------------------------------------------------------------*/
/**
* Creates the documentation markdown formatted for 'github' or 'site'.
*
* @private
* @param {string} type The format type.
*/
function build(type) {
const options = _.defaults({}, config.base, config[type]);
const markdown = docdown(options);
fs.writeFile(readmePath, postprocess(markdown), util.pitch);
}
build(_.last(process.argv));

View File

@@ -1,34 +0,0 @@
'use strict';
const _ = require('lodash');
const async = require('async');
const path = require('path');
const file = require('../common/file');
const util = require('../common/util');
const basePath = path.join(__dirname, '..', '..');
const distPath = path.join(basePath, 'dist');
const filePairs = [
[path.join(distPath, 'lodash.core.js'), 'core.js'],
[path.join(distPath, 'lodash.core.min.js'), 'core.min.js'],
[path.join(distPath, 'lodash.min.js'), 'lodash.min.js']
];
/*----------------------------------------------------------------------------*/
/**
* Creates supplementary Lodash modules at the `target` path.
*
* @private
* @param {string} target The output directory path.
*/
function build(target) {
const actions = _.map(filePairs, pair =>
file.copy(pair[0], path.join(target, pair[1])));
async.series(actions, util.pitch);
}
build(_.last(process.argv));

View File

@@ -1,224 +0,0 @@
'use strict';
const _ = require('lodash');
const cheerio = require('cheerio');
const fs = require('fs');
const marky = require('marky-markdown');
const path = require('path');
const util = require('../common/util');
const basePath = path.join(__dirname, '..', '..');
const docPath = path.join(basePath, 'doc');
const readmePath = path.join(docPath, 'README.md');
const highlights = {
'html': [
'string'
],
'js': [
'comment',
'console',
'delimiter',
'method',
'modifier',
'name',
'numeric',
'string',
'support',
'type'
]
};
const exts = _.keys(highlights);
/**
* Converts Lodash method references into documentation links.
*
* @private
* @param {Object} $ The Cheerio object.
*/
function autoLink($) {
$('.doc-container code').each(function() {
const $code = $(this);
const html = $code.html();
if (/^_\.\w+$/.test(html)) {
const id = html.split('.')[1];
$code.replaceWith(`<a href="#${ id }"><code>_.${ id }</code></a>`);
}
});
}
/**
* Removes horizontal rules from the document.
*
* @private
* @param {Object} $ The Cheerio object.
*/
function removeHorizontalRules($) {
$('hr').remove();
}
/**
* Removes marky-markdown specific ids and class names.
*
* @private
* @param {Object} $ The Cheerio object.
*/
function removeMarkyAttributes($) {
$('[id^="user-content-"]')
.attr('class', null)
.attr('id', null);
$(':header:not(h3) > a').each(function() {
const $a = $(this);
$a.replaceWith($a.html());
});
}
/**
* Renames "_" id and anchor references to "lodash".
*
* @private
* @param {Object} $ The Cheerio object.
*/
function renameLodashId($) {
$('#_').attr('id', 'lodash');
$('[href="#_"]').attr('href', '#lodash');
}
/**
* Repairs broken marky-markdown headers.
* See https://github.com/npm/marky-markdown/issues/217 for more details.
*
* @private
* @param {Object} $ The Cheerio object.
*/
function repairMarkyHeaders($) {
$('p:empty + h3').prev().remove();
$('h3 ~ p:empty').each(function() {
const $p = $(this);
let node = this.prev;
while ((node = node.prev) && node.name != 'h3' && node.name != 'p') {
$p.prepend(node.next);
}
});
$('h3 code em').parent().each(function() {
const $code = $(this);
$code.html($code.html().replace(/<\/?em>/g, '_'));
});
}
/**
* Cleans up highlights blocks by removing extraneous class names and elements.
*
* @private
* @param {Object} $ The Cheerio object.
*/
function tidyHighlights($) {
$('.highlight').each(function() {
let $spans;
const $parent = $(this);
const classes = $parent.find('.source,.text').first().attr('class').split(' ');
const ext = _(classes).intersection(exts).last();
$parent.addClass(ext);
// Remove line indicators for single line snippets.
$parent.children('pre').each(function() {
const $divs = $(this).children('div');
if ($divs.length == 1) {
$divs.replaceWith($divs.html());
}
});
// Remove extraneous class names.
$parent.find('[class]').each(function() {
const $element = $(this);
const classes = $element.attr('class').split(' ');
const attr = _(classes).intersection(highlights[ext]).join(' ');
$element.attr('class', attr || null);
});
// Collapse nested comment highlights.
$parent.find(`[class~="comment"]`).each(function() {
const $element = $(this);
$element.text($element.text().trim());
});
// Collapse nested string highlights.
$parent.find(`[class~="string"]`).each(function() {
const $element = $(this);
$element.text($element.text());
});
// Collapse nested spans.
while (($spans = $parent.find('span:not([class])')).length) {
$spans.each(function() {
let $span = $(this);
while ($span[0] && $span[0].name == 'span' && !$span.attr('class')) {
const $parent = $span.parent();
$span.replaceWith($span.html());
$span = $parent;
}
});
}
});
}
/*----------------------------------------------------------------------------*/
/**
* Creates the documentation HTML.
*
* @private
*/
function build() {
const markdown = fs
// Load markdown.
.readFileSync(readmePath, 'utf8')
// Uncomment docdown HTML hints.
.replace(/(<)!--\s*|\s*--(>)/g, '$1$2')
// Convert source and npm package links to anchors.
.replace(/\[source\]\(([^)]+)\) \[npm package\]\(([^)]+)\)/g, (match, href1, href2) =>
`<p><a href="${ href1 }">source</a> <a href="${ href2 }">npm package</a></p>`
);
const $ = cheerio.load(marky(markdown, {
'enableHeadingLinkIcons': false,
'sanitize': false
}));
const $header = $('h1').first().remove();
const version = $header.find('span').first().text().trim().slice(1);
// Auto-link Lodash method references.
autoLink($);
// Rename "_" id references to "lodash".
renameLodashId($);
// Remove docdown horizontal rules.
removeHorizontalRules($);
// Remove marky-markdown attribute additions.
removeMarkyAttributes($);
// Repair marky-markdown wrapping around headers.
repairMarkyHeaders($);
// Cleanup highlights.
tidyHighlights($);
const html = [
// Append YAML front matter.
'---',
'id: docs',
'layout: docs',
'title: Lodash Documentation',
'version: ' + (version || null),
'---',
'',
// Wrap in raw tags to avoid Liquid template tag processing.
'{% raw %}',
$.html().trim(),
'{% endraw %}',
''
].join('\n');
fs.writeFile(path.join(docPath, version + '.html'), html, util.pitch);
}
build();

15774
lodash.js

File diff suppressed because it is too large Load Diff

99
lodash.min.js vendored Normal file
View File

@@ -0,0 +1,99 @@
/**
* @license
* lodash 3.10.0 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
* Build: `lodash modern -o ./lodash.js`
*/
;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===w,u=n===n,o=null===t,i=t===w,f=t===t;if(n>t&&!o||!u||r&&!i&&f||e&&f)return 1;if(n<t&&!r||!f||o&&!e&&u||i&&u)return-1}return 0}function t(n,t,r){for(var e=n.length,u=r?e:-1;r?u--:++u<e;)if(t(n[u],u,n))return u;return-1}function r(n,t,r){if(t!==t)return p(n,r);r-=1;for(var e=n.length;++r<e;)if(n[r]===t)return r;return-1}function e(n){return typeof n=="function"||false}function u(n){return null==n?"":n+""}function o(n,t){for(var r=-1,e=n.length;++r<e&&-1<t.indexOf(n.charAt(r)););
return r}function i(n,t){for(var r=n.length;r--&&-1<t.indexOf(n.charAt(r)););return r}function f(t,r){return n(t.a,r.a)||t.b-r.b}function a(n){return Nn[n]}function c(n){return Tn[n]}function l(n,t,r){return t?n=Bn[n]:r&&(n=Dn[n]),"\\"+n}function s(n){return"\\"+Dn[n]}function p(n,t,r){var e=n.length;for(t+=r?0:-1;r?t--:++t<e;){var u=n[t];if(u!==u)return t}return-1}function h(n){return!!n&&typeof n=="object"}function _(n){return 160>=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n);
}function v(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;)n[r]===t&&(n[r]=z,o[++u]=r);return o}function g(n){for(var t=-1,r=n.length;++t<r&&_(n.charCodeAt(t)););return t}function y(n){for(var t=n.length;t--&&_(n.charCodeAt(t)););return t}function d(n){return Ln[n]}function m(_){function Nn(n){if(h(n)&&!(Oo(n)||n instanceof zn)){if(n instanceof Ln)return n;if(nu.call(n,"__chain__")&&nu.call(n,"__wrapped__"))return Mr(n)}return new Ln(n)}function Tn(){}function Ln(n,t,r){this.__wrapped__=n,this.__actions__=r||[],
this.__chain__=!!t}function zn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=Ru,this.__views__=[]}function Bn(){this.__data__={}}function Dn(n){var t=n?n.length:0;for(this.data={hash:gu(null),set:new lu};t--;)this.push(n[t])}function Mn(n,t){var r=n.data;return(typeof t=="string"||ge(t)?r.set.has(t):r.hash[t])?0:-1}function qn(n,t){var r=-1,e=n.length;for(t||(t=Be(e));++r<e;)t[r]=n[r];return t}function Pn(n,t){for(var r=-1,e=n.length;++r<e&&false!==t(n[r],r,n););
return n}function Kn(n,t){for(var r=-1,e=n.length;++r<e;)if(!t(n[r],r,n))return false;return true}function Vn(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;){var i=n[r];t(i,r,n)&&(o[++u]=i)}return o}function Gn(n,t){for(var r=-1,e=n.length,u=Be(e);++r<e;)u[r]=t(n[r],r,n);return u}function Jn(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function Xn(n,t,r,e){var u=-1,o=n.length;for(e&&o&&(r=n[++u]);++u<o;)r=t(r,n[u],u,n);return r}function Hn(n,t){for(var r=-1,e=n.length;++r<e;)if(t(n[r],r,n))return true;
return false}function Qn(n,t,r,e){return n!==w&&nu.call(e,r)?n:t}function nt(n,t,r){for(var e=-1,u=zo(t),o=u.length;++e<o;){var i=u[e],f=n[i],a=r(f,t[i],i,n,t);(a===a?a===f:f!==f)&&(f!==w||i in n)||(n[i]=a)}return n}function tt(n,t){return null==t?n:et(t,zo(t),n)}function rt(n,t){for(var r=-1,e=null==n,u=!e&&Er(n),o=u?n.length:0,i=t.length,f=Be(i);++r<i;){var a=t[r];f[r]=u?Cr(a,o)?n[a]:w:e?w:n[a]}return f}function et(n,t,r){r||(r={});for(var e=-1,u=t.length;++e<u;){var o=t[e];r[o]=n[o]}return r}function ut(n,t,r){
var e=typeof n;return"function"==e?t===w?n:Bt(n,t,r):null==n?Fe:"object"==e?bt(n):t===w?ze(n):xt(n,t)}function ot(n,t,r,e,u,o,i){var f;if(r&&(f=u?r(n,e,u):r(n)),f!==w)return f;if(!ge(n))return n;if(e=Oo(n)){if(f=kr(n),!t)return qn(n,f)}else{var a=ru.call(n),c=a==K;if(a!=Z&&a!=B&&(!c||u))return Fn[a]?Rr(n,a,t):u?n:{};if(f=Ir(c?{}:n),!t)return tt(f,n)}for(o||(o=[]),i||(i=[]),u=o.length;u--;)if(o[u]==n)return i[u];return o.push(n),i.push(f),(e?Pn:_t)(n,function(e,u){f[u]=ot(e,t,r,u,n,o,i)}),f}function it(n,t,r){
if(typeof n!="function")throw new Ge(L);return su(function(){n.apply(w,r)},t)}function ft(n,t){var e=n?n.length:0,u=[];if(!e)return u;var o=-1,i=xr(),f=i==r,a=f&&t.length>=F&&gu&&lu?new Dn(t):null,c=t.length;a&&(i=Mn,f=false,t=a);n:for(;++o<e;)if(a=n[o],f&&a===a){for(var l=c;l--;)if(t[l]===a)continue n;u.push(a)}else 0>i(t,a,0)&&u.push(a);return u}function at(n,t){var r=true;return Su(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,o=u;return Su(n,function(n,i,f){i=+t(n,i,f),(r(i,u)||i===e&&i===o)&&(u=i,
o=n)}),o}function lt(n,t){var r=[];return Su(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function st(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function pt(n,t,r,e){e||(e=[]);for(var u=-1,o=n.length;++u<o;){var i=n[u];h(i)&&Er(i)&&(r||Oo(i)||pe(i))?t?pt(i,t,r,e):Jn(e,i):r||(e[e.length]=i)}return e}function ht(n,t){Nu(n,t,Re)}function _t(n,t){return Nu(n,t,zo)}function vt(n,t){return Tu(n,t,zo)}function gt(n,t){for(var r=-1,e=t.length,u=-1,o=[];++r<e;){var i=t[r];
ve(n[i])&&(o[++u]=i)}return o}function yt(n,t,r){if(null!=n){r!==w&&r in Br(n)&&(t=[r]),r=0;for(var e=t.length;null!=n&&r<e;)n=n[t[r++]];return r&&r==e?n:w}}function dt(n,t,r,e,u,o){if(n===t)n=true;else if(null==n||null==t||!ge(n)&&!h(t))n=n!==n&&t!==t;else n:{var i=dt,f=Oo(n),a=Oo(t),c=D,l=D;f||(c=ru.call(n),c==B?c=Z:c!=Z&&(f=xe(n))),a||(l=ru.call(t),l==B?l=Z:l!=Z&&xe(t));var s=c==Z,a=l==Z,l=c==l;if(!l||f||s){if(!e&&(c=s&&nu.call(n,"__wrapped__"),a=a&&nu.call(t,"__wrapped__"),c||a)){n=i(c?n.value():n,a?t.value():t,r,e,u,o);
break n}if(l){for(u||(u=[]),o||(o=[]),c=u.length;c--;)if(u[c]==n){n=o[c]==t;break n}u.push(n),o.push(t),n=(f?yr:mr)(n,t,i,r,e,u,o),u.pop(),o.pop()}else n=false}else n=dr(n,t,c)}return n}function mt(n,t,r){var e=t.length,u=e,o=!r;if(null==n)return!u;for(n=Br(n);e--;){var i=t[e];if(o&&i[2]?i[1]!==n[i[0]]:!(i[0]in n))return false}for(;++e<u;){var i=t[e],f=i[0],a=n[f],c=i[1];if(o&&i[2]){if(a===w&&!(f in n))return false}else if(i=r?r(a,c,f):w,i===w?!dt(c,a,r,true):!i)return false}return true}function wt(n,t){var r=-1,e=Er(n)?Be(n.length):[];
return Su(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function bt(n){var t=Ar(n);if(1==t.length&&t[0][2]){var r=t[0][0],e=t[0][1];return function(n){return null==n?false:n[r]===e&&(e!==w||r in Br(n))}}return function(n){return mt(n,t)}}function xt(n,t){var r=Oo(n),e=Wr(n)&&t===t&&!ge(t),u=n+"";return n=Dr(n),function(o){if(null==o)return false;var i=u;if(o=Br(o),!(!r&&e||i in o)){if(o=1==n.length?o:yt(o,Et(n,0,-1)),null==o)return false;i=Zr(n),o=Br(o)}return o[i]===t?t!==w||i in o:dt(t,o[i],w,true)}}function At(n,t,r,e,u){
if(!ge(n))return n;var o=Er(t)&&(Oo(t)||xe(t)),i=o?w:zo(t);return Pn(i||t,function(f,a){if(i&&(a=f,f=t[a]),h(f)){e||(e=[]),u||(u=[]);n:{for(var c=a,l=e,s=u,p=l.length,_=t[c];p--;)if(l[p]==_){n[c]=s[p];break n}var p=n[c],v=r?r(p,_,c,n,t):w,g=v===w;g&&(v=_,Er(_)&&(Oo(_)||xe(_))?v=Oo(p)?p:Er(p)?qn(p):[]:me(_)||pe(_)?v=pe(p)?ke(p):me(p)?p:{}:g=false),l.push(_),s.push(v),g?n[c]=At(v,_,r,l,s):(v===v?v!==p:p===p)&&(n[c]=v)}}else c=n[a],l=r?r(c,f,a,n,t):w,(s=l===w)&&(l=f),l===w&&(!o||a in n)||!s&&(l===l?l===c:c!==c)||(n[a]=l);
}),n}function jt(n){return function(t){return null==t?w:t[n]}}function kt(n){var t=n+"";return n=Dr(n),function(r){return yt(r,n,t)}}function It(n,t){for(var r=n?t.length:0;r--;){var e=t[r];if(e!=u&&Cr(e)){var u=e;pu.call(n,e,1)}}}function Rt(n,t){return n+yu(ku()*(t-n+1))}function Ot(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function Et(n,t,r){var e=-1,u=n.length;for(t=null==t?0:+t||0,0>t&&(t=-t>u?0:u+t),r=r===w||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Be(u);++e<u;)r[e]=n[e+t];
return r}function Ct(n,t){var r;return Su(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function Ut(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function Wt(t,r,e){var u=wr(),o=-1;return r=Gn(r,function(n){return u(n)}),t=wt(t,function(n){return{a:Gn(r,function(t){return t(n)}),b:++o,c:n}}),Ut(t,function(t,r){var u;n:{for(var o=-1,i=t.a,f=r.a,a=i.length,c=e.length;++o<a;)if(u=n(i[o],f[o])){if(o>=c)break n;o=e[o],u*="asc"===o||true===o?1:-1;break n}u=t.b-r.b}return u})}function $t(n,t){
var r=0;return Su(n,function(n,e,u){r+=+t(n,e,u)||0}),r}function St(n,t){var e=-1,u=xr(),o=n.length,i=u==r,f=i&&o>=F,a=f&&gu&&lu?new Dn(void 0):null,c=[];a?(u=Mn,i=false):(f=false,a=t?[]:c);n:for(;++e<o;){var l=n[e],s=t?t(l,e,n):l;if(i&&l===l){for(var p=a.length;p--;)if(a[p]===s)continue n;t&&a.push(s),c.push(l)}else 0>u(a,s,0)&&((t||f)&&a.push(s),c.push(l))}return c}function Ft(n,t){for(var r=-1,e=t.length,u=Be(e);++r<e;)u[r]=n[t[r]];return u}function Nt(n,t,r,e){for(var u=n.length,o=e?u:-1;(e?o--:++o<u)&&t(n[o],o,n););
return r?Et(n,e?0:o,e?o+1:u):Et(n,e?o+1:0,e?u:o)}function Tt(n,t){var r=n;r instanceof zn&&(r=r.value());for(var e=-1,u=t.length;++e<u;)var o=t[e],r=o.func.apply(o.thisArg,Jn([r],o.args));return r}function Lt(n,t,r){var e=0,u=n?n.length:e;if(typeof t=="number"&&t===t&&u<=Eu){for(;e<u;){var o=e+u>>>1,i=n[o];(r?i<=t:i<t)&&null!==i?e=o+1:u=o}return u}return zt(n,t,Fe,r)}function zt(n,t,r,e){t=r(t);for(var u=0,o=n?n.length:0,i=t!==t,f=null===t,a=t===w;u<o;){var c=yu((u+o)/2),l=r(n[c]),s=l!==w,p=l===l;
(i?p||e:f?p&&s&&(e||null!=l):a?p&&(e||s):null==l?0:e?l<=t:l<t)?u=c+1:o=c}return xu(o,Ou)}function Bt(n,t,r){if(typeof n!="function")return Fe;if(t===w)return n;switch(r){case 1:return function(r){return n.call(t,r)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,o){return n.call(t,r,e,u,o)};case 5:return function(r,e,u,o,i){return n.call(t,r,e,u,o,i)}}return function(){return n.apply(t,arguments)}}function Dt(n){var t=new ou(n.byteLength);return new hu(t).set(new hu(n)),
t}function Mt(n,t,r){for(var e=r.length,u=-1,o=bu(n.length-e,0),i=-1,f=t.length,a=Be(f+o);++i<f;)a[i]=t[i];for(;++u<e;)a[r[u]]=n[u];for(;o--;)a[i++]=n[u++];return a}function qt(n,t,r){for(var e=-1,u=r.length,o=-1,i=bu(n.length-u,0),f=-1,a=t.length,c=Be(i+a);++o<i;)c[o]=n[o];for(i=o;++f<a;)c[i+f]=t[f];for(;++e<u;)c[i+r[e]]=n[o++];return c}function Pt(n,t){return function(r,e,u){var o=t?t():{};if(e=wr(e,u,3),Oo(r)){u=-1;for(var i=r.length;++u<i;){var f=r[u];n(o,f,e(f,u,r),r)}}else Su(r,function(t,r,u){
n(o,t,e(t,r,u),u)});return o}}function Kt(n){return le(function(t,r){var e=-1,u=null==t?0:r.length,o=2<u?r[u-2]:w,i=2<u?r[2]:w,f=1<u?r[u-1]:w;for(typeof o=="function"?(o=Bt(o,f,5),u-=2):(o=typeof f=="function"?f:w,u-=o?1:0),i&&Ur(r[0],r[1],i)&&(o=3>u?w:o,u=1);++e<u;)(i=r[e])&&n(t,i,o);return t})}function Vt(n,t){return function(r,e){var u=r?Bu(r):0;if(!Sr(u))return n(r,e);for(var o=t?u:-1,i=Br(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}function Zt(n){return function(t,r,e){var u=Br(t);e=e(t);for(var o=e.length,i=n?o:-1;n?i--:++i<o;){
var f=e[i];if(false===r(u[f],f,u))break}return t}}function Yt(n,t){function r(){return(this&&this!==Zn&&this instanceof r?e:n).apply(t,arguments)}var e=Jt(n);return r}function Gt(n){return function(t){var r=-1;t=$e(Ce(t));for(var e=t.length,u="";++r<e;)u=n(u,t[r],r);return u}}function Jt(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:
return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=$u(n.prototype),t=n.apply(r,t);return ge(t)?t:r}}function Xt(n){function t(r,e,u){return u&&Ur(r,e,u)&&(e=w),r=gr(r,n,w,w,w,w,w,e),r.placeholder=t.placeholder,r}return t}function Ht(n,t){return le(function(r){var e=r[0];return null==e?e:(r.push(t),n.apply(w,r))})}function Qt(n,t){return function(r,e,u){if(u&&Ur(r,e,u)&&(e=w),e=wr(e,u,3),1==e.length){
u=r=Oo(r)?r:zr(r);for(var o=e,i=-1,f=u.length,a=t,c=a;++i<f;){var l=u[i],s=+o(l);n(s,a)&&(a=s,c=l)}if(u=c,!r.length||u!==t)return u}return ct(r,e,n,t)}}function nr(n,r){return function(e,u,o){return u=wr(u,o,3),Oo(e)?(u=t(e,u,r),-1<u?e[u]:w):st(e,u,n)}}function tr(n){return function(r,e,u){return r&&r.length?(e=wr(e,u,3),t(r,e,n)):-1}}function rr(n){return function(t,r,e){return r=wr(r,e,3),st(t,r,n,true)}}function er(n){return function(){for(var t,r=arguments.length,e=n?r:-1,u=0,o=Be(r);n?e--:++e<r;){
var i=o[u++]=arguments[e];if(typeof i!="function")throw new Ge(L);!t&&Ln.prototype.thru&&"wrapper"==br(i)&&(t=new Ln([],true))}for(e=t?-1:r;++e<r;){var i=o[e],u=br(i),f="wrapper"==u?zu(i):w;t=f&&$r(f[0])&&f[1]==(E|k|R|C)&&!f[4].length&&1==f[9]?t[br(f[0])].apply(t,f[3]):1==i.length&&$r(i)?t[u]():t.thru(i)}return function(){var n=arguments,e=n[0];if(t&&1==n.length&&Oo(e)&&e.length>=F)return t.plant(e).value();for(var u=0,n=r?o[u].apply(this,n):e;++u<r;)n=o[u].call(this,n);return n}}}function ur(n,t){
return function(r,e,u){return typeof e=="function"&&u===w&&Oo(r)?n(r,e):t(r,Bt(e,u,3))}}function or(n){return function(t,r,e){return(typeof r!="function"||e!==w)&&(r=Bt(r,e,3)),n(t,r,Re)}}function ir(n){return function(t,r,e){return(typeof r!="function"||e!==w)&&(r=Bt(r,e,3)),n(t,r)}}function fr(n){return function(t,r,e){var u={};return r=wr(r,e,3),_t(t,function(t,e,o){o=r(t,e,o),e=n?o:e,t=n?t:o,u[e]=t}),u}}function ar(n){return function(t,r,e){return t=u(t),(n?t:"")+pr(t,r,e)+(n?"":t)}}function cr(n){
var t=le(function(r,e){var u=v(e,t.placeholder);return gr(r,n,w,e,u)});return t}function lr(n,t){return function(r,e,u,o){var i=3>arguments.length;return typeof e=="function"&&o===w&&Oo(r)?n(r,e,u,i):Ot(r,wr(e,o,4),u,i,t)}}function sr(n,t,r,e,u,o,i,f,a,c){function l(){for(var m=arguments.length,b=m,j=Be(m);b--;)j[b]=arguments[b];if(e&&(j=Mt(j,e,u)),o&&(j=qt(j,o,i)),_||y){var b=l.placeholder,k=v(j,b),m=m-k.length;if(m<c){var I=f?qn(f):w,m=bu(c-m,0),E=_?k:w,k=_?w:k,C=_?j:w,j=_?w:j;return t|=_?R:O,t&=~(_?O:R),
g||(t&=~(x|A)),j=[n,t,r,C,E,j,k,I,a,m],I=sr.apply(w,j),$r(n)&&Du(I,j),I.placeholder=b,I}}if(b=p?r:this,I=h?b[n]:n,f)for(m=j.length,E=xu(f.length,m),k=qn(j);E--;)C=f[E],j[E]=Cr(C,m)?k[C]:w;return s&&a<j.length&&(j.length=a),this&&this!==Zn&&this instanceof l&&(I=d||Jt(n)),I.apply(b,j)}var s=t&E,p=t&x,h=t&A,_=t&k,g=t&j,y=t&I,d=h?w:Jt(n);return l}function pr(n,t,r){return n=n.length,t=+t,n<t&&mu(t)?(t-=n,r=null==r?" ":r+"",Ue(r,vu(t/r.length)).slice(0,t)):""}function hr(n,t,r,e){function u(){for(var t=-1,f=arguments.length,a=-1,c=e.length,l=Be(c+f);++a<c;)l[a]=e[a];
for(;f--;)l[a++]=arguments[++t];return(this&&this!==Zn&&this instanceof u?i:n).apply(o?r:this,l)}var o=t&x,i=Jt(n);return u}function _r(n){var t=Pe[n];return function(n,r){return(r=r===w?0:+r||0)?(r=au(10,r),t(n*r)/r):t(n)}}function vr(n){return function(t,r,e,u){var o=wr(e);return null==e&&o===ut?Lt(t,r,n):zt(t,r,o(e,u,1),n)}}function gr(n,t,r,e,u,o,i,f){var a=t&A;if(!a&&typeof n!="function")throw new Ge(L);var c=e?e.length:0;if(c||(t&=~(R|O),e=u=w),c-=u?u.length:0,t&O){var l=e,s=u;e=u=w}var p=a?w:zu(n);
return r=[n,t,r,e,u,l,s,o,i,f],p&&(e=r[1],t=p[1],f=e|t,u=t==E&&e==k||t==E&&e==C&&r[7].length<=p[8]||t==(E|C)&&e==k,(f<E||u)&&(t&x&&(r[2]=p[2],f|=e&x?0:j),(e=p[3])&&(u=r[3],r[3]=u?Mt(u,e,p[4]):qn(e),r[4]=u?v(r[3],z):qn(p[4])),(e=p[5])&&(u=r[5],r[5]=u?qt(u,e,p[6]):qn(e),r[6]=u?v(r[5],z):qn(p[6])),(e=p[7])&&(r[7]=qn(e)),t&E&&(r[8]=null==r[8]?p[8]:xu(r[8],p[8])),null==r[9]&&(r[9]=p[9]),r[0]=p[0],r[1]=f),t=r[1],f=r[9]),r[9]=null==f?a?0:n.length:bu(f-c,0)||0,(p?Lu:Du)(t==x?Yt(r[0],r[2]):t!=R&&t!=(x|R)||r[4].length?sr.apply(w,r):hr.apply(w,r),r);
}function yr(n,t,r,e,u,o,i){var f=-1,a=n.length,c=t.length;if(a!=c&&(!u||c<=a))return false;for(;++f<a;){var l=n[f],c=t[f],s=e?e(u?c:l,u?l:c,f):w;if(s!==w){if(s)continue;return false}if(u){if(!Hn(t,function(n){return l===n||r(l,n,e,u,o,i)}))return false}else if(l!==c&&!r(l,c,e,u,o,i))return false}return true}function dr(n,t,r){switch(r){case M:case q:return+n==+t;case P:return n.name==t.name&&n.message==t.message;case V:return n!=+n?t!=+t:n==+t;case Y:case G:return n==t+""}return false}function mr(n,t,r,e,u,o,i){var f=zo(n),a=f.length,c=zo(t).length;
if(a!=c&&!u)return false;for(c=a;c--;){var l=f[c];if(!(u?l in t:nu.call(t,l)))return false}for(var s=u;++c<a;){var l=f[c],p=n[l],h=t[l],_=e?e(u?h:p,u?p:h,l):w;if(_===w?!r(p,h,e,u,o,i):!_)return false;s||(s="constructor"==l)}return s||(r=n.constructor,e=t.constructor,!(r!=e&&"constructor"in n&&"constructor"in t)||typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)?true:false}function wr(n,t,r){var e=Nn.callback||Se,e=e===Se?ut:e;return r?e(n,t,r):e}function br(n){for(var t=n.name,r=Wu[t],e=r?r.length:0;e--;){
var u=r[e],o=u.func;if(null==o||o==n)return u.name}return t}function xr(n,t,e){var u=Nn.indexOf||Vr,u=u===Vr?r:u;return n?u(n,t,e):u}function Ar(n){n=Oe(n);for(var t=n.length;t--;){var r=n[t][1];n[t][2]=r===r&&!ge(r)}return n}function jr(n,t){var r=null==n?w:n[t];return ye(r)?r:w}function kr(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&nu.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ir(n){return n=n.constructor,typeof n=="function"&&n instanceof n||(n=Ve),
new n}function Rr(n,t,r){var e=n.constructor;switch(t){case J:return Dt(n);case M:case q:return new e(+n);case X:case H:case Q:case nn:case tn:case rn:case en:case un:case on:return t=n.buffer,new e(r?Dt(t):t,n.byteOffset,n.length);case V:case G:return new e(n);case Y:var u=new e(n.source,kn.exec(n));u.lastIndex=n.lastIndex}return u}function Or(n,t,r){return null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),t=Zr(t)),t=null==n?n:n[t],null==t?w:t.apply(n,r)}function Er(n){return null!=n&&Sr(Bu(n));
}function Cr(n,t){return n=typeof n=="number"||On.test(n)?+n:-1,t=null==t?Cu:t,-1<n&&0==n%1&&n<t}function Ur(n,t,r){if(!ge(r))return false;var e=typeof t;return("number"==e?Er(r)&&Cr(t,r.length):"string"==e&&t in r)?(t=r[t],n===n?n===t:t!==t):false}function Wr(n,t){var r=typeof n;return"string"==r&&dn.test(n)||"number"==r?true:Oo(n)?false:!yn.test(n)||null!=t&&n in Br(t)}function $r(n){var t=br(n);return t in zn.prototype?(t=Nn[t],n===t?true:(t=zu(t),!!t&&n===t[0])):false}function Sr(n){return typeof n=="number"&&-1<n&&0==n%1&&n<=Cu;
}function Fr(n,t){return n===w?t:Eo(n,t,Fr)}function Nr(n,t){n=Br(n);for(var r=-1,e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u}function Tr(n,t){var r={};return ht(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r}function Lr(n){for(var t=Re(n),r=t.length,e=r&&n.length,u=!!e&&Sr(e)&&(Oo(n)||pe(n)),o=-1,i=[];++o<r;){var f=t[o];(u&&Cr(f,e)||nu.call(n,f))&&i.push(f)}return i}function zr(n){return null==n?[]:Er(n)?ge(n)?n:Ve(n):Ee(n)}function Br(n){return ge(n)?n:Ve(n)}function Dr(n){if(Oo(n))return n;
var t=[];return u(n).replace(mn,function(n,r,e,u){t.push(e?u.replace(An,"$1"):r||n)}),t}function Mr(n){return n instanceof zn?n.clone():new Ln(n.__wrapped__,n.__chain__,qn(n.__actions__))}function qr(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0>t?0:t)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0,0>t?0:t)):[]}function Kr(n){return n?n[0]:w}function Vr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e=="number")e=0>e?bu(u+e,0):e;else if(e)return e=Lt(n,t),
e<u&&(t===t?t===n[e]:n[e]!==n[e])?e:-1;return r(n,t,e||0)}function Zr(n){var t=n?n.length:0;return t?n[t-1]:w}function Yr(n){return qr(n,1)}function Gr(n,t,e,u){if(!n||!n.length)return[];null!=t&&typeof t!="boolean"&&(u=e,e=Ur(n,t,u)?w:t,t=false);var o=wr();if((null!=e||o!==ut)&&(e=o(e,u,3)),t&&xr()==r){t=e;var i;e=-1,u=n.length;for(var o=-1,f=[];++e<u;){var a=n[e],c=t?t(a,e,n):a;e&&i===c||(i=c,f[++o]=a)}n=f}else n=St(n,e);return n}function Jr(n){if(!n||!n.length)return[];var t=-1,r=0;n=Vn(n,function(n){
return Er(n)?(r=bu(n.length,r),true):void 0});for(var e=Be(r);++t<r;)e[t]=Gn(n,jt(t));return e}function Xr(n,t,r){return n&&n.length?(n=Jr(n),null==t?n:(t=Bt(t,r,4),Gn(n,function(n){return Xn(n,t,w,true)}))):[]}function Hr(n,t){var r=-1,e=n?n.length:0,u={};for(!e||t||Oo(n[0])||(t=[]);++r<e;){var o=n[r];t?u[o]=t[r]:o&&(u[o[0]]=o[1])}return u}function Qr(n){return n=Nn(n),n.__chain__=true,n}function ne(n,t,r){return t.call(r,n)}function te(n,t,r){var e=Oo(n)?Kn:at;return r&&Ur(n,t,r)&&(t=w),(typeof t!="function"||r!==w)&&(t=wr(t,r,3)),
e(n,t)}function re(n,t,r){var e=Oo(n)?Vn:lt;return t=wr(t,r,3),e(n,t)}function ee(n,t,r,e){var u=n?Bu(n):0;return Sr(u)||(n=Ee(n),u=n.length),r=typeof r!="number"||e&&Ur(t,r,e)?0:0>r?bu(u+r,0):r||0,typeof n=="string"||!Oo(n)&&be(n)?r<=u&&-1<n.indexOf(t,r):!!u&&-1<xr(n,t,r)}function ue(n,t,r){var e=Oo(n)?Gn:wt;return t=wr(t,r,3),e(n,t)}function oe(n,t,r){if(r?Ur(n,t,r):null==t){n=zr(n);var e=n.length;return 0<e?n[Rt(0,e-1)]:w}r=-1,n=je(n);var e=n.length,u=e-1;for(t=xu(0>t?0:+t||0,e);++r<t;){var e=Rt(r,u),o=n[e];
n[e]=n[r],n[r]=o}return n.length=t,n}function ie(n,t,r){var e=Oo(n)?Hn:Ct;return r&&Ur(n,t,r)&&(t=w),(typeof t!="function"||r!==w)&&(t=wr(t,r,3)),e(n,t)}function fe(n,t){var r;if(typeof t!="function"){if(typeof n!="function")throw new Ge(L);var e=n;n=t,t=e}return function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=w),r}}function ae(n,t,r){function e(t,r){r&&iu(r),a=p=h=w,t&&(_=ho(),c=n.apply(s,f),p||a||(f=s=w))}function u(){var n=t-(ho()-l);0>=n||n>t?e(h,a):p=su(u,n)}function o(){e(g,p);
}function i(){if(f=arguments,l=ho(),s=this,h=g&&(p||!y),false===v)var r=y&&!p;else{a||y||(_=l);var e=v-(l-_),i=0>=e||e>v;i?(a&&(a=iu(a)),_=l,c=n.apply(s,f)):a||(a=su(o,e))}return i&&p?p=iu(p):p||t===v||(p=su(u,t)),r&&(i=true,c=n.apply(s,f)),!i||p||a||(f=s=w),c}var f,a,c,l,s,p,h,_=0,v=false,g=true;if(typeof n!="function")throw new Ge(L);if(t=0>t?0:+t||0,true===r)var y=true,g=false;else ge(r)&&(y=!!r.leading,v="maxWait"in r&&bu(+r.maxWait||0,t),g="trailing"in r?!!r.trailing:g);return i.cancel=function(){p&&iu(p),a&&iu(a),
_=0,a=p=h=w},i}function ce(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)}if(typeof n!="function"||t&&typeof t!="function")throw new Ge(L);return r.cache=new ce.Cache,r}function le(n,t){if(typeof n!="function")throw new Ge(L);return t=bu(t===w?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=bu(r.length-t,0),o=Be(u);++e<u;)o[e]=r[t+e];switch(t){case 0:return n.call(this,o);case 1:return n.call(this,r[0],o);
case 2:return n.call(this,r[0],r[1],o)}for(u=Be(t+1),e=-1;++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function se(n,t){return n>t}function pe(n){return h(n)&&Er(n)&&nu.call(n,"callee")&&!cu.call(n,"callee")}function he(n,t,r,e){return e=(r=typeof r=="function"?Bt(r,e,3):w)?r(n,t):w,e===w?dt(n,t,r):!!e}function _e(n){return h(n)&&typeof n.message=="string"&&ru.call(n)==P}function ve(n){return ge(n)&&ru.call(n)==K}function ge(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function ye(n){
return null==n?false:ve(n)?uu.test(Qe.call(n)):h(n)&&Rn.test(n)}function de(n){return typeof n=="number"||h(n)&&ru.call(n)==V}function me(n){var t;if(!h(n)||ru.call(n)!=Z||pe(n)||!(nu.call(n,"constructor")||(t=n.constructor,typeof t!="function"||t instanceof t)))return false;var r;return ht(n,function(n,t){r=t}),r===w||nu.call(n,r)}function we(n){return ge(n)&&ru.call(n)==Y}function be(n){return typeof n=="string"||h(n)&&ru.call(n)==G}function xe(n){return h(n)&&Sr(n.length)&&!!Sn[ru.call(n)]}function Ae(n,t){
return n<t}function je(n){var t=n?Bu(n):0;return Sr(t)?t?qn(n):[]:Ee(n)}function ke(n){return et(n,Re(n))}function Ie(n){return gt(n,Re(n))}function Re(n){if(null==n)return[];ge(n)||(n=Ve(n));for(var t=n.length,t=t&&Sr(t)&&(Oo(n)||pe(n))&&t||0,r=n.constructor,e=-1,r=typeof r=="function"&&r.prototype===n,u=Be(t),o=0<t;++e<t;)u[e]=e+"";for(var i in n)o&&Cr(i,t)||"constructor"==i&&(r||!nu.call(n,i))||u.push(i);return u}function Oe(n){n=Br(n);for(var t=-1,r=zo(n),e=r.length,u=Be(e);++t<e;){var o=r[t];
u[t]=[o,n[o]]}return u}function Ee(n){return Ft(n,zo(n))}function Ce(n){return(n=u(n))&&n.replace(En,a).replace(xn,"")}function Ue(n,t){var r="";if(n=u(n),t=+t,1>t||!n||!mu(t))return r;do t%2&&(r+=n),t=yu(t/2),n+=n;while(t);return r}function We(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(g(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,r){return r&&Ur(n,t,r)&&(t=w),n=u(n),n.match(t||Wn)||[]}function Se(n,t,r){return r&&Ur(n,t,r)&&(t=w),h(n)?Ne(n):ut(n,t)}function Fe(n){
return n}function Ne(n){return bt(ot(n,true))}function Te(n,t,r){if(null==r){var e=ge(t),u=e?zo(t):w;((u=u&&u.length?gt(t,u):w)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=gt(t,zo(t)));var o=true,e=-1,i=ve(n),f=u.length;false===r?o=false:ge(r)&&"chain"in r&&(o=r.chain);for(;++e<f;){r=u[e];var a=t[r];n[r]=a,i&&(n.prototype[r]=function(t){return function(){var r=this.__chain__;if(o||r){var e=n(this.__wrapped__);return(e.__actions__=qn(this.__actions__)).push({func:t,args:arguments,thisArg:n}),e.__chain__=r,e}return t.apply(n,Jn([this.value()],arguments));
}}(a))}return n}function Le(){}function ze(n){return Wr(n)?jt(n):kt(n)}_=_?Yn.defaults(Zn.Object(),_,Yn.pick(Zn,$n)):Zn;var Be=_.Array,De=_.Date,Me=_.Error,qe=_.Function,Pe=_.Math,Ke=_.Number,Ve=_.Object,Ze=_.RegExp,Ye=_.String,Ge=_.TypeError,Je=Be.prototype,Xe=Ve.prototype,He=Ye.prototype,Qe=qe.prototype.toString,nu=Xe.hasOwnProperty,tu=0,ru=Xe.toString,eu=Zn._,uu=Ze("^"+Qe.call(nu).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ou=_.ArrayBuffer,iu=_.clearTimeout,fu=_.parseFloat,au=Pe.pow,cu=Xe.propertyIsEnumerable,lu=jr(_,"Set"),su=_.setTimeout,pu=Je.splice,hu=_.Uint8Array,_u=jr(_,"WeakMap"),vu=Pe.ceil,gu=jr(Ve,"create"),yu=Pe.floor,du=jr(Be,"isArray"),mu=_.isFinite,wu=jr(Ve,"keys"),bu=Pe.max,xu=Pe.min,Au=jr(De,"now"),ju=_.parseInt,ku=Pe.random,Iu=Ke.NEGATIVE_INFINITY,Ru=Ke.POSITIVE_INFINITY,Ou=4294967294,Eu=2147483647,Cu=9007199254740991,Uu=_u&&new _u,Wu={};
Nn.support={},Nn.templateSettings={escape:_n,evaluate:vn,interpolate:gn,variable:"",imports:{_:Nn}};var $u=function(){function n(){}return function(t){if(ge(t)){n.prototype=t;var r=new n;n.prototype=w}return r||{}}}(),Su=Vt(_t),Fu=Vt(vt,true),Nu=Zt(),Tu=Zt(true),Lu=Uu?function(n,t){return Uu.set(n,t),n}:Fe,zu=Uu?function(n){return Uu.get(n)}:Le,Bu=jt("length"),Du=function(){var n=0,t=0;return function(r,e){var u=ho(),o=S-(u-t);if(t=u,0<o){if(++n>=$)return r}else n=0;return Lu(r,e)}}(),Mu=le(function(n,t){
return h(n)&&Er(n)?ft(n,pt(t,false,true)):[]}),qu=tr(),Pu=tr(true),Ku=le(function(n){for(var t=n.length,e=t,u=Be(l),o=xr(),i=o==r,f=[];e--;){var a=n[e]=Er(a=n[e])?a:[];u[e]=i&&120<=a.length&&gu&&lu?new Dn(e&&a):null}var i=n[0],c=-1,l=i?i.length:0,s=u[0];n:for(;++c<l;)if(a=i[c],0>(s?Mn(s,a):o(f,a,0))){for(e=t;--e;){var p=u[e];if(0>(p?Mn(p,a):o(n[e],a,0)))continue n}s&&s.push(a),f.push(a)}return f}),Vu=le(function(t,r){r=pt(r);var e=rt(t,r);return It(t,r.sort(n)),e}),Zu=vr(),Yu=vr(true),Gu=le(function(n){return St(pt(n,false,true));
}),Ju=le(function(n,t){return Er(n)?ft(n,t):[]}),Xu=le(Jr),Hu=le(function(n){var t=n.length,r=2<t?n[t-2]:w,e=1<t?n[t-1]:w;return 2<t&&typeof r=="function"?t-=2:(r=1<t&&typeof e=="function"?(--t,e):w,e=w),n.length=t,Xr(n,r,e)}),Qu=le(function(n){return n=pt(n),this.thru(function(t){t=Oo(t)?t:[Br(t)];for(var r=n,e=-1,u=t.length,o=-1,i=r.length,f=Be(u+i);++e<u;)f[e]=t[e];for(;++o<i;)f[e++]=r[o];return f})}),no=le(function(n,t){return rt(n,pt(t))}),to=Pt(function(n,t,r){nu.call(n,r)?++n[r]:n[r]=1}),ro=nr(Su),eo=nr(Fu,true),uo=ur(Pn,Su),oo=ur(function(n,t){
for(var r=n.length;r--&&false!==t(n[r],r,n););return n},Fu),io=Pt(function(n,t,r){nu.call(n,r)?n[r].push(t):n[r]=[t]}),fo=Pt(function(n,t,r){n[r]=t}),ao=le(function(n,t,r){var e=-1,u=typeof t=="function",o=Wr(t),i=Er(n)?Be(n.length):[];return Su(n,function(n){var f=u?t:o&&null!=n?n[t]:w;i[++e]=f?f.apply(n,r):Or(n,t,r)}),i}),co=Pt(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),lo=lr(Xn,Su),so=lr(function(n,t,r,e){var u=n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r},Fu),po=le(function(n,t){
if(null==n)return[];var r=t[2];return r&&Ur(t[0],t[1],r)&&(t.length=1),Wt(n,pt(t),[])}),ho=Au||function(){return(new De).getTime()},_o=le(function(n,t,r){var e=x;if(r.length)var u=v(r,_o.placeholder),e=e|R;return gr(n,e,t,r,u)}),vo=le(function(n,t){t=t.length?pt(t):Ie(n);for(var r=-1,e=t.length;++r<e;){var u=t[r];n[u]=gr(n[u],x,n)}return n}),go=le(function(n,t,r){var e=x|A;if(r.length)var u=v(r,go.placeholder),e=e|R;return gr(t,e,n,r,u)}),yo=Xt(k),mo=Xt(I),wo=le(function(n,t){return it(n,1,t)}),bo=le(function(n,t,r){
return it(n,t,r)}),xo=er(),Ao=er(true),jo=le(function(n,t){if(t=pt(t),typeof n!="function"||!Kn(t,e))throw new Ge(L);var r=t.length;return le(function(e){for(var u=xu(e.length,r);u--;)e[u]=t[u](e[u]);return n.apply(this,e)})}),ko=cr(R),Io=cr(O),Ro=le(function(n,t){return gr(n,C,w,w,w,pt(t))}),Oo=du||function(n){return h(n)&&Sr(n.length)&&ru.call(n)==D},Eo=Kt(At),Co=Kt(function(n,t,r){return r?nt(n,t,r):tt(n,t)}),Uo=Ht(Co,function(n,t){return n===w?t:n}),Wo=Ht(Eo,Fr),$o=rr(_t),So=rr(vt),Fo=or(Nu),No=or(Tu),To=ir(_t),Lo=ir(vt),zo=wu?function(n){
var t=null==n?w:n.constructor;return typeof t=="function"&&t.prototype===n||typeof n!="function"&&Er(n)?Lr(n):ge(n)?wu(n):[]}:Lr,Bo=fr(true),Do=fr(),Mo=le(function(n,t){if(null==n)return{};if("function"!=typeof t[0])return t=Gn(pt(t),Ye),Nr(n,ft(Re(n),t));var r=Bt(t[0],t[1],3);return Tr(n,function(n,t,e){return!r(n,t,e)})}),qo=le(function(n,t){return null==n?{}:"function"==typeof t[0]?Tr(n,Bt(t[0],t[1],3)):Nr(n,pt(t))}),Po=Gt(function(n,t,r){return t=t.toLowerCase(),n+(r?t.charAt(0).toUpperCase()+t.slice(1):t);
}),Ko=Gt(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Vo=ar(),Zo=ar(true),Yo=Gt(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Go=Gt(function(n,t,r){return n+(r?" ":"")+(t.charAt(0).toUpperCase()+t.slice(1))}),Jo=le(function(n,t){try{return n.apply(w,t)}catch(r){return _e(r)?r:new Me(r)}}),Xo=le(function(n,t){return function(r){return Or(r,n,t)}}),Ho=le(function(n,t){return function(r){return Or(n,r,t)}}),Qo=_r("ceil"),ni=_r("floor"),ti=Qt(se,Iu),ri=Qt(Ae,Ru),ei=_r("round");return Nn.prototype=Tn.prototype,
Ln.prototype=$u(Tn.prototype),Ln.prototype.constructor=Ln,zn.prototype=$u(Tn.prototype),zn.prototype.constructor=zn,Bn.prototype["delete"]=function(n){return this.has(n)&&delete this.__data__[n]},Bn.prototype.get=function(n){return"__proto__"==n?w:this.__data__[n]},Bn.prototype.has=function(n){return"__proto__"!=n&&nu.call(this.__data__,n)},Bn.prototype.set=function(n,t){return"__proto__"!=n&&(this.__data__[n]=t),this},Dn.prototype.push=function(n){var t=this.data;typeof n=="string"||ge(n)?t.set.add(n):t.hash[n]=true;
},ce.Cache=Bn,Nn.after=function(n,t){if(typeof t!="function"){if(typeof n!="function")throw new Ge(L);var r=n;n=t,t=r}return n=mu(n=+n)?n:0,function(){return 1>--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Ur(n,t,r)&&(t=w),t=n&&null==t?n.length:bu(+t||0,0),gr(n,E,w,w,w,w,t)},Nn.assign=Co,Nn.at=no,Nn.before=fe,Nn.bind=_o,Nn.bindAll=vo,Nn.bindKey=go,Nn.callback=Se,Nn.chain=Qr,Nn.chunk=function(n,t,r){t=(r?Ur(n,t,r):null==t)?1:bu(yu(t)||1,1),r=0;for(var e=n?n.length:0,u=-1,o=Be(vu(e/t));r<e;)o[++u]=Et(n,r,r+=t);
return o},Nn.compact=function(n){for(var t=-1,r=n?n.length:0,e=-1,u=[];++t<r;){var o=n[t];o&&(u[++e]=o)}return u},Nn.constant=function(n){return function(){return n}},Nn.countBy=to,Nn.create=function(n,t,r){var e=$u(n);return r&&Ur(n,t,r)&&(t=w),t?tt(e,t):e},Nn.curry=yo,Nn.curryRight=mo,Nn.debounce=ae,Nn.defaults=Uo,Nn.defaultsDeep=Wo,Nn.defer=wo,Nn.delay=bo,Nn.difference=Mu,Nn.drop=qr,Nn.dropRight=Pr,Nn.dropRightWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3),true,true):[]},Nn.dropWhile=function(n,t,r){
return n&&n.length?Nt(n,wr(t,r,3),true):[]},Nn.fill=function(n,t,r,e){var u=n?n.length:0;if(!u)return[];for(r&&typeof r!="number"&&Ur(n,t,r)&&(r=0,e=u),u=n.length,r=null==r?0:+r||0,0>r&&(r=-r>u?0:u+r),e=e===w||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;r<u;)n[r++]=t;return n},Nn.filter=re,Nn.flatten=function(n,t,r){var e=n?n.length:0;return r&&Ur(n,t,r)&&(t=false),e?pt(n,t):[]},Nn.flattenDeep=function(n){return n&&n.length?pt(n,true):[]},Nn.flow=xo,Nn.flowRight=Ao,Nn.forEach=uo,Nn.forEachRight=oo,Nn.forIn=Fo,
Nn.forInRight=No,Nn.forOwn=To,Nn.forOwnRight=Lo,Nn.functions=Ie,Nn.groupBy=io,Nn.indexBy=fo,Nn.initial=function(n){return Pr(n,1)},Nn.intersection=Ku,Nn.invert=function(n,t,r){r&&Ur(n,t,r)&&(t=w),r=-1;for(var e=zo(n),u=e.length,o={};++r<u;){var i=e[r],f=n[i];t?nu.call(o,f)?o[f].push(i):o[f]=[i]:o[f]=i}return o},Nn.invoke=ao,Nn.keys=zo,Nn.keysIn=Re,Nn.map=ue,Nn.mapKeys=Bo,Nn.mapValues=Do,Nn.matches=Ne,Nn.matchesProperty=function(n,t){return xt(n,ot(t,true))},Nn.memoize=ce,Nn.merge=Eo,Nn.method=Xo,Nn.methodOf=Ho,
Nn.mixin=Te,Nn.modArgs=jo,Nn.negate=function(n){if(typeof n!="function")throw new Ge(L);return function(){return!n.apply(this,arguments)}},Nn.omit=Mo,Nn.once=function(n){return fe(2,n)},Nn.pairs=Oe,Nn.partial=ko,Nn.partialRight=Io,Nn.partition=co,Nn.pick=qo,Nn.pluck=function(n,t){return ue(n,ze(t))},Nn.property=ze,Nn.propertyOf=function(n){return function(t){return yt(n,Dr(t),t+"")}},Nn.pull=function(){var n=arguments,t=n[0];if(!t||!t.length)return t;for(var r=0,e=xr(),u=n.length;++r<u;)for(var o=0,i=n[r];-1<(o=e(t,i,o));)pu.call(t,o,1);
return t},Nn.pullAt=Vu,Nn.range=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w),n=+n||0,r=null==r?1:+r||0,null==t?(t=n,n=0):t=+t||0;var e=-1;t=bu(vu((t-n)/(r||1)),0);for(var u=Be(t);++e<t;)u[e]=n,n+=r;return u},Nn.rearg=Ro,Nn.reject=function(n,t,r){var e=Oo(n)?Vn:lt;return t=wr(t,r,3),e(n,function(n,r,e){return!t(n,r,e)})},Nn.remove=function(n,t,r){var e=[];if(!n||!n.length)return e;var u=-1,o=[],i=n.length;for(t=wr(t,r,3);++u<i;)r=n[u],t(r,u,n)&&(e.push(r),o.push(u));return It(n,o),e},Nn.rest=Yr,Nn.restParam=le,
Nn.set=function(n,t,r){if(null==n)return n;var e=t+"";t=null!=n[e]||Wr(t,n)?[e]:Dr(t);for(var e=-1,u=t.length,o=u-1,i=n;null!=i&&++e<u;){var f=t[e];ge(i)&&(e==o?i[f]=r:null==i[f]&&(i[f]=Cr(t[e+1])?[]:{})),i=i[f]}return n},Nn.shuffle=function(n){return oe(n,Ru)},Nn.slice=function(n,t,r){var e=n?n.length:0;return e?(r&&typeof r!="number"&&Ur(n,t,r)&&(t=0,r=e),Et(n,t,r)):[]},Nn.sortBy=function(n,t,r){if(null==n)return[];r&&Ur(n,t,r)&&(t=w);var e=-1;return t=wr(t,r,3),n=wt(n,function(n,r,u){return{a:t(n,r,u),
b:++e,c:n}}),Ut(n,f)},Nn.sortByAll=po,Nn.sortByOrder=function(n,t,r,e){return null==n?[]:(e&&Ur(t,r,e)&&(r=w),Oo(t)||(t=null==t?[]:[t]),Oo(r)||(r=null==r?[]:[r]),Wt(n,t,r))},Nn.spread=function(n){if(typeof n!="function")throw new Ge(L);return function(t){return n.apply(this,t)}},Nn.take=function(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0,0>t?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){
return n&&n.length?Nt(n,wr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3)):[]},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new Ge(L);return false===r?e=false:ge(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ae(n,t,{leading:e,maxWait:+t,trailing:u})},Nn.thru=ne,Nn.times=function(n,t,r){if(n=yu(n),1>n||!mu(n))return[];var e=-1,u=Be(xu(n,4294967295));for(t=Bt(t,r,1);++e<n;)4294967295>e?u[e]=t(e):t(e);
return u},Nn.toArray=je,Nn.toPlainObject=ke,Nn.transform=function(n,t,r,e){var u=Oo(n)||xe(n);return t=wr(t,e,4),null==r&&(u||ge(n)?(e=n.constructor,r=u?Oo(n)?new e:[]:$u(ve(e)?e.prototype:w)):r={}),(u?Pn:_t)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=Gu,Nn.uniq=Gr,Nn.unzip=Jr,Nn.unzipWith=Xr,Nn.values=Ee,Nn.valuesIn=function(n){return Ft(n,Re(n))},Nn.where=function(n,t){return re(n,bt(t))},Nn.without=Ju,Nn.wrap=function(n,t){return t=null==t?Fe:t,gr(t,R,w,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++n<t;){
var r=arguments[n];if(Er(r))var e=e?Jn(ft(e,r),ft(r,e)):r}return e?St(e):[]},Nn.zip=Xu,Nn.zipObject=Hr,Nn.zipWith=Hu,Nn.backflow=Ao,Nn.collect=ue,Nn.compose=Ao,Nn.each=uo,Nn.eachRight=oo,Nn.extend=Co,Nn.iteratee=Se,Nn.methods=Ie,Nn.object=Hr,Nn.select=re,Nn.tail=Yr,Nn.unique=Gr,Te(Nn,Nn),Nn.add=function(n,t){return(+n||0)+(+t||0)},Nn.attempt=Jo,Nn.camelCase=Po,Nn.capitalize=function(n){return(n=u(n))&&n.charAt(0).toUpperCase()+n.slice(1)},Nn.ceil=Qo,Nn.clone=function(n,t,r,e){return t&&typeof t!="boolean"&&Ur(n,t,r)?t=false:typeof t=="function"&&(e=r,
r=t,t=false),typeof r=="function"?ot(n,t,Bt(r,e,1)):ot(n,t)},Nn.cloneDeep=function(n,t,r){return typeof t=="function"?ot(n,true,Bt(t,r,1)):ot(n,true)},Nn.deburr=Ce,Nn.endsWith=function(n,t,r){n=u(n),t+="";var e=n.length;return r=r===w?e:xu(0>r?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&hn.test(n)?n.replace(sn,c):n},Nn.escapeRegExp=function(n){return(n=u(n))&&bn.test(n)?n.replace(wn,l):n||"(?:)"},Nn.every=te,Nn.find=ro,Nn.findIndex=qu,Nn.findKey=$o,Nn.findLast=eo,
Nn.findLastIndex=Pu,Nn.findLastKey=So,Nn.findWhere=function(n,t){return ro(n,bt(t))},Nn.first=Kr,Nn.floor=ni,Nn.get=function(n,t,r){return n=null==n?w:yt(n,Dr(t),t+""),n===w?r:n},Nn.gt=se,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=nu.call(n,t);if(!r&&!Wr(t)){if(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),null==n)return false;t=Zr(t),r=nu.call(n,t)}return r||Sr(n.length)&&Cr(t,n.length)&&(Oo(n)||pe(n))},Nn.identity=Fe,Nn.includes=ee,Nn.indexOf=Vr,Nn.inRange=function(n,t,r){
return t=+t||0,r===w?(r=t,t=0):r=+r||0,n>=xu(t,r)&&n<bu(t,r)},Nn.isArguments=pe,Nn.isArray=Oo,Nn.isBoolean=function(n){return true===n||false===n||h(n)&&ru.call(n)==M},Nn.isDate=function(n){return h(n)&&ru.call(n)==q},Nn.isElement=function(n){return!!n&&1===n.nodeType&&h(n)&&!me(n)},Nn.isEmpty=function(n){return null==n?true:Er(n)&&(Oo(n)||be(n)||pe(n)||h(n)&&ve(n.splice))?!n.length:!zo(n).length},Nn.isEqual=he,Nn.isError=_e,Nn.isFinite=function(n){return typeof n=="number"&&mu(n)},Nn.isFunction=ve,Nn.isMatch=function(n,t,r,e){
return r=typeof r=="function"?Bt(r,e,3):w,mt(n,Ar(t),r)},Nn.isNaN=function(n){return de(n)&&n!=+n},Nn.isNative=ye,Nn.isNull=function(n){return null===n},Nn.isNumber=de,Nn.isObject=ge,Nn.isPlainObject=me,Nn.isRegExp=we,Nn.isString=be,Nn.isTypedArray=xe,Nn.isUndefined=function(n){return n===w},Nn.kebabCase=Ko,Nn.last=Zr,Nn.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(typeof r=="number")u=(0>r?bu(e+r,0):xu(r||0,e-1))+1;else if(r)return u=Lt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1;
if(t!==t)return p(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=Ae,Nn.lte=function(n,t){return n<=t},Nn.max=ti,Nn.min=ri,Nn.noConflict=function(){return Zn._=eu,this},Nn.noop=Le,Nn.now=ho,Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return e<t&&mu(t)?(e=(t-e)/2,t=yu(e),e=vu(e),r=pr("",e,r),r.slice(0,t)+n+r):n},Nn.padLeft=Vo,Nn.padRight=Zo,Nn.parseInt=function(n,t,r){return(r?Ur(n,t,r):null==t)?t=0:t&&(t=+t),n=We(n),ju(n,t||(In.test(n)?16:10))},Nn.random=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w);
var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=ku(),xu(n+r*(t-n+fu("1e-"+((r+"").length-1))),t)):Rt(n,t)},Nn.reduce=lo,Nn.reduceRight=so,Nn.repeat=Ue,Nn.result=function(n,t,r){var e=null==n?w:n[t];return e===w&&(null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),e=null==n?w:n[Zr(t)]),e=e===w?r:e),ve(e)?e.call(n):e},Nn.round=ei,Nn.runInContext=m,Nn.size=function(n){var t=n?Bu(n):0;
return Sr(t)?t:zo(n).length},Nn.snakeCase=Yo,Nn.some=ie,Nn.sortedIndex=Zu,Nn.sortedLastIndex=Yu,Nn.startCase=Go,Nn.startsWith=function(n,t,r){return n=u(n),r=null==r?0:xu(0>r?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){if(r&&Ur(n,t,r)&&(t=w),t=wr(t,r,3),1==t.length){n=Oo(n)?n:zr(n),r=n.length;for(var e=0;r--;)e+=+t(n[r])||0;n=e}else n=$t(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Ur(n,t,r)&&(t=r=w),n=u(n),t=nt(tt({},r||t),e,Qn),r=nt(tt({},t.imports),e.imports,Qn);
var o,i,f=zo(r),a=Ft(r,f),c=0;r=t.interpolate||Cn;var l="__p+='";r=Ze((t.escape||Cn).source+"|"+r.source+"|"+(r===gn?jn:Cn).source+"|"+(t.evaluate||Cn).source+"|$","g");var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,f,a){return e||(e=u),l+=n.slice(c,a).replace(Un,s),r&&(o=true,l+="'+__e("+r+")+'"),f&&(i=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),c=a+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(i?l.replace(fn,""):l).replace(an,"$1").replace(cn,"$1;"),
l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(o?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Jo(function(){return qe(f,p+"return "+l).apply(w,a)}),t.source=l,_e(t))throw t;return t},Nn.trim=We,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Ur(e,t,r):null==t)?g(n):o(n,t+"")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n;
},Nn.trunc=function(n,t,r){r&&Ur(n,t,r)&&(t=w);var e=U;if(r=W,null!=t)if(ge(t)){var o="separator"in t?t.separator:o,e="length"in t?+t.length||0:e;r="omission"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length,1>e)return r;if(t=n.slice(0,e),null==o)return t+r;if(we(o)){if(n.slice(e).search(o)){var i,f=n.slice(0,e);for(o.global||(o=Ze(o.source,(kn.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(f);)i=n.index;t=t.slice(0,null==i?e:i)}}else n.indexOf(o,e)!=e&&(o=t.lastIndexOf(o),
-1<o&&(t=t.slice(0,o)));return t+r},Nn.unescape=function(n){return(n=u(n))&&pn.test(n)?n.replace(ln,d):n},Nn.uniqueId=function(n){var t=++tu;return u(n)+t},Nn.words=$e,Nn.all=te,Nn.any=ie,Nn.contains=ee,Nn.eq=he,Nn.detect=ro,Nn.foldl=lo,Nn.foldr=so,Nn.head=Kr,Nn.include=ee,Nn.inject=lo,Te(Nn,function(){var n={};return _t(Nn,function(t,r){Nn.prototype[r]||(n[r]=t)}),n}(),false),Nn.sample=oe,Nn.prototype.sample=function(n){return this.__chain__||null!=n?this.thru(function(t){return oe(t,n)}):oe(this.value());
},Nn.VERSION=b,Pn("bind bindKey curry curryRight partial partialRight".split(" "),function(n){Nn[n].placeholder=Nn}),Pn(["drop","take"],function(n,t){zn.prototype[n]=function(r){var e=this.__filtered__;if(e&&!t)return new zn(this);r=null==r?1:bu(yu(r)||0,0);var u=this.clone();return e?u.__takeCount__=xu(u.__takeCount__,r):u.__views__.push({size:r,type:n+(0>u.__dir__?"Right":"")}),u},zn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Pn(["filter","map","takeWhile"],function(n,t){
var r=t+1,e=r!=T;zn.prototype[n]=function(n,t){var u=this.clone();return u.__iteratees__.push({iteratee:wr(n,t,1),type:r}),u.__filtered__=u.__filtered__||e,u}}),Pn(["first","last"],function(n,t){var r="take"+(t?"Right":"");zn.prototype[n]=function(){return this[r](1).value()[0]}}),Pn(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");zn.prototype[n]=function(){return this.__filtered__?new zn(this):this[r](1)}}),Pn(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?bt:ze;zn.prototype[n]=function(n){
return this[r](e(n))}}),zn.prototype.compact=function(){return this.filter(Fe)},zn.prototype.reject=function(n,t){return n=wr(n,t,1),this.filter(function(t){return!n(t)})},zn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return r.__filtered__&&(0<n||0>t)?new zn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==w&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r)},zn.prototype.takeRightWhile=function(n,t){return this.reverse().takeWhile(n,t).reverse()},zn.prototype.toArray=function(){return this.take(Ru);
},_t(zn.prototype,function(n,t){var r=/^(?:filter|map|reject)|While$/.test(t),e=/^(?:first|last)$/.test(t),u=Nn[e?"take"+("last"==t?"Right":""):t];u&&(Nn.prototype[t]=function(){function t(n){return e&&i?u(n,1)[0]:u.apply(w,Jn([n],o))}var o=e?[1]:arguments,i=this.__chain__,f=this.__wrapped__,a=!!this.__actions__.length,c=f instanceof zn,l=o[0],s=c||Oo(f);return s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false),l={func:ne,args:[t],thisArg:w},a=c&&!a,e&&!i?a?(f=f.clone(),f.__actions__.push(l),n.call(f)):u.call(w,this.value())[0]:!e&&s?(f=a?f:new zn(this),
f=n.apply(f,o),f.__actions__.push(l),new Ln(f,i)):this.thru(t)})}),Pn("join pop push replace shift sort splice split unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?He:Je)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),_t(zn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name;(Wu[e]||(Wu[e]=[])).push({
name:t,func:r})}}),Wu[sr(w,A).name]=[{name:"wrapper",func:w}],zn.prototype.clone=function(){var n=new zn(this.__wrapped__);return n.__actions__=qn(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=qn(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=qn(this.__views__),n},zn.prototype.reverse=function(){if(this.__filtered__){var n=new zn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},zn.prototype.value=function(){
var n,t=this.__wrapped__.value(),r=this.__dir__,e=Oo(t),u=0>r,o=e?t.length:0;n=o;for(var i=this.__views__,f=0,a=-1,c=i.length;++a<c;){var l=i[a],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=xu(n,f+s);break;case"takeRight":f=bu(f,n-s)}}if(n={start:f,end:n},i=n.start,f=n.end,n=f-i,i=u?f:i-1,f=this.__iteratees__,a=f.length,c=0,l=xu(n,this.__takeCount__),!e||o<F||o==n&&l==n)return Tt(u&&e?t.reverse():t,this.__actions__);e=[];n:for(;n--&&c<l;){for(i+=r,u=-1,o=t[i];++u<a;){
var p=f[u],s=p.type,p=p.iteratee(o);if(s==T)o=p;else if(!p){if(s==N)continue n;break n}}e[c++]=o}return e},Nn.prototype.chain=function(){return Qr(this)},Nn.prototype.commit=function(){return new Ln(this.value(),this.__chain__)},Nn.prototype.concat=Qu,Nn.prototype.plant=function(n){for(var t,r=this;r instanceof Tn;){var e=Mr(r);t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},Nn.prototype.reverse=function(){function n(n){return r&&0>r.__dir__?n:n.reverse()}var t=this.__wrapped__;
if(t instanceof zn){var r=t;return this.__actions__.length&&(r=new zn(this)),r=r.reverse(),r.__actions__.push({func:ne,args:[n],thisArg:w}),new Ln(r,this.__chain__)}return this.thru(n)},Nn.prototype.toString=function(){return this.value()+""},Nn.prototype.run=Nn.prototype.toJSON=Nn.prototype.valueOf=Nn.prototype.value=function(){return Tt(this.__wrapped__,this.__actions__)},Nn.prototype.collect=Nn.prototype.map,Nn.prototype.head=Nn.prototype.first,Nn.prototype.select=Nn.prototype.filter,Nn.prototype.tail=Nn.prototype.rest,
Nn}var w,b="3.10.0",x=1,A=2,j=4,k=8,I=16,R=32,O=64,E=128,C=256,U=30,W="...",$=150,S=16,F=200,N=1,T=2,L="Expected a function",z="__lodash_placeholder__",B="[object Arguments]",D="[object Array]",M="[object Boolean]",q="[object Date]",P="[object Error]",K="[object Function]",V="[object Number]",Z="[object Object]",Y="[object RegExp]",G="[object String]",J="[object ArrayBuffer]",X="[object Float32Array]",H="[object Float64Array]",Q="[object Int8Array]",nn="[object Int16Array]",tn="[object Int32Array]",rn="[object Uint8Array]",en="[object Uint8ClampedArray]",un="[object Uint16Array]",on="[object Uint32Array]",fn=/\b__p\+='';/g,an=/\b(__p\+=)''\+/g,cn=/(__e\(.*?\)|\b__t\))\+'';/g,ln=/&(?:amp|lt|gt|quot|#39|#96);/g,sn=/[&<>"'`]/g,pn=RegExp(ln.source),hn=RegExp(sn.source),_n=/<%-([\s\S]+?)%>/g,vn=/<%([\s\S]+?)%>/g,gn=/<%=([\s\S]+?)%>/g,yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,dn=/^\w*$/,mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,wn=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,bn=RegExp(wn.source),xn=/[\u0300-\u036f\ufe20-\ufe23]/g,An=/\\(\\)?/g,jn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,kn=/\w*$/,In=/^0[xX]/,Rn=/^\[object .+?Constructor\]$/,On=/^\d+$/,En=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Cn=/($^)/,Un=/['\n\r\u2028\u2029\\]/g,Wn=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?=[A-Z\\xc0-\\xd6\\xd8-\\xde][a-z\\xdf-\\xf6\\xf8-\\xff]+)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|[0-9]+","g"),$n="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap".split(" "),Sn={};
Sn[X]=Sn[H]=Sn[Q]=Sn[nn]=Sn[tn]=Sn[rn]=Sn[en]=Sn[un]=Sn[on]=true,Sn[B]=Sn[D]=Sn[J]=Sn[M]=Sn[q]=Sn[P]=Sn[K]=Sn["[object Map]"]=Sn[V]=Sn[Z]=Sn[Y]=Sn["[object Set]"]=Sn[G]=Sn["[object WeakMap]"]=false;var Fn={};Fn[B]=Fn[D]=Fn[J]=Fn[M]=Fn[q]=Fn[X]=Fn[H]=Fn[Q]=Fn[nn]=Fn[tn]=Fn[V]=Fn[Z]=Fn[Y]=Fn[G]=Fn[rn]=Fn[en]=Fn[un]=Fn[on]=true,Fn[P]=Fn[K]=Fn["[object Map]"]=Fn["[object Set]"]=Fn["[object WeakMap]"]=false;var Nn={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a",
"\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y",
"\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"},Tn={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","`":"&#96;"},Ln={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&#96;":"`"},zn={"function":true,object:true},Bn={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"},Dn={"\\":"\\",
"'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mn=zn[typeof exports]&&exports&&!exports.nodeType&&exports,qn=zn[typeof module]&&module&&!module.nodeType&&module,Pn=zn[typeof self]&&self&&self.Object&&self,Kn=zn[typeof window]&&window&&window.Object&&window,Vn=qn&&qn.exports===Mn&&Mn,Zn=Mn&&qn&&typeof global=="object"&&global&&global.Object&&global||Kn!==(this&&this.window)&&Kn||Pn||this,Yn=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=Yn, define(function(){
return Yn})):Mn&&qn?Vn?(qn.exports=Yn)._=Yn:Mn._=Yn:Zn._=Yn}).call(this);

12555
lodash.src.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,66 +1,33 @@
{
"name": "lodash",
"version": "4.17.5",
"license": "MIT",
"version": "3.10.0",
"main": "lodash.src.js",
"private": true,
"main": "lodash.js",
"engines": {
"node": ">=4.0.0"
},
"scripts": {
"build": "npm run build:main && npm run build:fp",
"build:fp": "node lib/fp/build-dist.js",
"build:fp-modules": "node lib/fp/build-modules.js",
"build:main": "node lib/main/build-dist.js",
"build:main-modules": "node lib/main/build-modules.js",
"doc": "node lib/main/build-doc github && npm run test:doc",
"doc:fp": "node lib/fp/build-doc",
"doc:site": "node lib/main/build-doc site",
"doc:sitehtml": "optional-dev-dependency marky-markdown@^9.0.1 && npm run doc:site && node lib/main/build-site",
"pretest": "npm run build",
"style": "npm run style:main && npm run style:fp && npm run style:perf && npm run style:test",
"style:fp": "jscs fp/*.js lib/**/*.js",
"style:main": "jscs lodash.js",
"style:perf": "jscs perf/*.js perf/**/*.js",
"style:test": "jscs test/*.js test/**/*.js",
"test": "npm run test:main && npm run test:fp",
"test:doc": "markdown-doctest doc/*.md",
"test:fp": "node test/test-fp",
"test:main": "node test/test",
"validate": "npm run style && npm run test"
},
"devDependencies": {
"async": "^2.1.4",
"benchmark": "^2.1.3",
"chalk": "^1.1.3",
"cheerio": "^0.22.0",
"codecov.io": "~0.1.6",
"coveralls": "^2.11.15",
"curl-amd": "~0.8.12",
"docdown": "~0.7.2",
"dojo": "^1.12.1",
"ecstatic": "^2.1.0",
"fs-extra": "~1.0.0",
"glob": "^7.1.1",
"istanbul": "0.4.5",
"jquery": "^3.1.1",
"jscs": "^3.0.7",
"lodash": "4.17.3",
"lodash-doc-globals": "^0.1.1",
"markdown-doctest": "^0.9.1",
"optional-dev-dependency": "^2.0.0",
"platform": "^1.3.3",
"qunit-extras": "^3.0.0",
"qunitjs": "^2.1.0",
"request": "^2.79.0",
"requirejs": "^2.3.2",
"sauce-tunnel": "^2.5.0",
"uglify-js": "2.7.5",
"webpack": "^1.14.0"
"curl-amd": "0.8.12",
"dojo": "~1.10.0",
"jquery": "~1.11.0",
"platform": "~1.3.0",
"qunit-extras": "~1.4.0",
"qunitjs": "~1.18.0",
"requirejs": "~2.1.0"
},
"greenkeeper": {
"volo": {
"type": "directory",
"ignore": [
"lodash"
".*",
"*.custom.*",
"*.log",
"*.map",
"*.md",
"lodash.src.js",
"bower.json",
"component.json",
"doc",
"node_modules",
"perf",
"test",
"vendor"
]
}
}

View File

@@ -15,8 +15,27 @@
/*--------------------------------------------------------------------------*/
/**
* Registers an event listener on an element.
*
* @private
* @param {Element} element The element.
* @param {string} eventName The name of the event.
* @param {Function} handler The event handler.
* @returns {Element} The element.
*/
function addListener(element, eventName, handler) {
if (typeof element.addEventListener != 'undefined') {
element.addEventListener(eventName, handler, false);
} else if (typeof element.attachEvent != 'undefined') {
element.attachEvent('on' + eventName, handler);
}
}
/*--------------------------------------------------------------------------*/
// Initialize controls.
addEventListener('load', function() {
addListener(window, 'load', function() {
function eventHandler(event) {
var buildIndex = buildList.selectedIndex,
otherIndex = otherList.selectedIndex,
@@ -39,7 +58,10 @@
span1.innerHTML =
'<label for="perf-build">Build: </label>' +
'<select id="perf-build">' +
'<option value="lodash">lodash (production)</option>' +
'<option value="lodash-compat">lodash (compat)</option>' +
'<option value="lodash-modern">lodash (modern)</option>' +
'<option value="lodash-custom-dev">lodash (custom development)</option>' +
'<option value="lodash-custom">lodash (custom production)</option>' +
'</select>';
var span2 = document.createElement('span');
@@ -49,7 +71,10 @@
'<select id="perf-other">' +
'<option value="underscore-dev">Underscore (development)</option>' +
'<option value="underscore">Underscore (production)</option>' +
'<option value="lodash">lodash</option>' +
'<option value="lodash-compat">lodash (compat)</option>' +
'<option value="lodash-modern">lodash (modern)</option>' +
'<option value="lodash-custom-dev">lodash (custom development)</option>' +
'<option value="lodash-custom">lodash (custom production)</option>' +
'</select>';
var buildList = span1.lastChild,
@@ -61,8 +86,11 @@
buildList.selectedIndex = (function() {
switch (build) {
case 'lodash':
case null: return 0;
case 'lodash-compat': return 0;
case 'lodash-custom-dev': return 2;
case 'lodash-custom': return 3;
case 'lodash-modern':
case null: return 1;
}
return -1;
}());
@@ -70,23 +98,29 @@
otherList.selectedIndex = (function() {
switch (other) {
case 'underscore-dev': return 0;
case 'lodash': return 2;
case 'lodash-compat': return 2;
case 'lodash-modern': return 3;
case 'lodash-custom-dev': return 4;
case 'lodash-custom': return 5;
case 'underscore':
case null: return 1;
}
return -1;
}());
buildList.addEventListener('change', eventHandler);
otherList.addEventListener('change', eventHandler);
addListener(buildList, 'change', eventHandler);
addListener(otherList, 'change', eventHandler);
});
// The lodash build file path.
ui.buildPath = (function() {
var result;
switch (build) {
case null: build = 'lodash';
case 'lodash': result = 'dist/lodash.min.js'; break;
case 'lodash-compat': result = 'lodash.compat.min.js'; break;
case 'lodash-custom-dev': result = 'lodash.custom.js'; break;
case 'lodash-custom': result = 'lodash.custom.min.js'; break;
case null: build = 'lodash-modern';
case 'lodash-modern': result = 'lodash.min.js'; break;
default: return build;
}
return basePath + result;
@@ -96,7 +130,10 @@
ui.otherPath = (function() {
var result;
switch (other) {
case 'lodash': result = 'dist/lodash.min.js'; break;
case 'lodash-compat': result = 'lodash.compat.min.js'; break;
case 'lodash-modern': result = 'lodash.min.js'; break;
case 'lodash-custom-dev': result = 'lodash.custom.js'; break;
case 'lodash-custom': result = 'lodash.custom.min.js'; break;
case 'underscore-dev': result = 'vendor/underscore/underscore.js'; break;
case null: other = 'underscore';
case 'underscore': result = 'vendor/underscore/underscore-min.js'; break;

View File

@@ -9,35 +9,28 @@
padding: 0;
height: 100%;
}
applet {
position: absolute;
left: -9999em;
}
#FirebugUI {
top: 2.5em;
top: 2em;
}
#perf-toolbar {
background-color: #EEE;
color: #5E740B;
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
font-size: small;
padding: 0.5em 1em 0.5em 1em;
padding: 0.5em 0 0.5em 2em;
overflow: hidden;
}
#perf-toolbar label {
display: inline-block;
margin-right: 0.5em;
}
#perf-toolbar span {
display: inline-block;
float: right;
line-height: 2.1em;
margin-left: 1em;
margin-top: 0;
}
</style>
</head>
<body>
<div id="perf-toolbar"></div>
<script src="../lodash.js"></script>
<script src="../node_modules/platform/platform.js"></script>
<script src="../node_modules/benchmark/benchmark.js"></script>
<script src="../lodash.src.js"></script>
<script src="../vendor/benchmark.js/benchmark.js"></script>
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
<script src="./asset/perf-ui.js"></script>
<script>
@@ -73,6 +66,15 @@
setTimeout(run, 15);
}
// is the applet permitted?
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
// is the applet really needed?
while (!(measured = new Date - begin)) {}
if (measured > 1 && !((perfNow = window.performance) && typeof (perfNow.now || perfNow.webkitNow) == 'function')) {
// load applet
document.write('<applet code="nano" archive="../vendor/benchmark.js/nano.jar"></applet>');
}
}
window.onload = init;
}());
</script>

View File

@@ -1,5 +1,4 @@
;(function() {
'use strict';
/** Used to access the Firebug Lite panel (set by `run`). */
var fbPanel;
@@ -39,16 +38,16 @@
result = params;
}
var last = result[result.length - 1];
result = (result.length > min && !/perf(?:\.js)?$/.test(last)) ? last : '../lodash.js';
result = (result.length > min && !/perf(?:\.js)?$/.test(last)) ? last : '../lodash.src.js';
if (!amd) {
try {
result = require('fs').realpathSync(result);
} catch (e) {}
} catch(e) {}
try {
result = require.resolve(result);
} catch (e) {}
} catch(e) {}
}
return result;
}());
@@ -83,10 +82,19 @@
/** Used to queue benchmark suites. */
var suites = [];
/** Used to resolve a value's internal [[Class]]. */
var toString = Object.prototype.toString;
/** Detect if in a browser environment. */
var isBrowser = isHostType(root, 'document') && isHostType(root, 'navigator');
/** Detect if in a Java environment. */
var isJava = !isBrowser && /Java/.test(toString.call(root.java));
/** Use a single "load" function. */
var load = (typeof require == 'function' && !amd)
? require
: noop;
: (isJava && root.load) || noop;
/** Load lodash. */
var lodash = root.lodash || (root.lodash = (
@@ -96,19 +104,19 @@
lodash.noConflict()
));
/** Load Underscore. */
var _ = root.underscore || (root.underscore = (
_ = load('../vendor/underscore/underscore.js') || root._,
_._ || _
));
/** Load Benchmark.js. */
var Benchmark = root.Benchmark || (root.Benchmark = (
Benchmark = load('../node_modules/benchmark/benchmark.js') || root.Benchmark,
Benchmark = load('../vendor/benchmark.js/benchmark.js') || root.Benchmark,
Benchmark = Benchmark.Benchmark || Benchmark,
Benchmark.runInContext(lodash.extend({}, root, { '_': lodash }))
));
/** Load Underscore. */
var _ = root._ || (root._ = (
_ = load('../vendor/underscore/underscore.js') || root._,
_._ || _
));
/*--------------------------------------------------------------------------*/
/**
@@ -197,7 +205,7 @@
fbPanel.getElementById('fbPanel1');
log('\nSit back and relax, this may take a while.');
suites[0].run({ 'async': true });
suites[0].run({ 'async': !isJava });
}
/*--------------------------------------------------------------------------*/
@@ -250,7 +258,7 @@
if (suites.length) {
// Run next suite.
suites[0].run({ 'async': true });
suites[0].run({ 'async': !isJava });
}
else {
var aMeanHz = getGeometricMean(score.a),
@@ -276,7 +284,7 @@
lodash.extend(Benchmark.options, {
'async': true,
'setup': '\
var _ = global.underscore,\
var _ = global._,\
lodash = global.lodash,\
belt = this.name == buildName ? lodash : _;\
\
@@ -343,8 +351,8 @@
square = function(v) { return v * v; };\
\
var largeArray = belt.range(10000),\
_chaining = _(largeArray).chain(),\
lodashChaining = lodash(largeArray).chain();\
_chaining = _.chain ? _(largeArray).chain() : _(largeArray),\
lodashChaining = lodash(largeArray);\
}\
if (typeof compact != "undefined") {\
var uncompacted = numbers.slice();\
@@ -352,13 +360,13 @@
uncompacted[6] = null;\
uncompacted[18] = "";\
}\
if (typeof flowRight != "undefined") {\
if (typeof compose != "undefined") {\
var compAddOne = function(n) { return n + 1; },\
compAddTwo = function(n) { return n + 2; },\
compAddThree = function(n) { return n + 3; };\
\
var _composed = _.flowRight && _.flowRight(compAddThree, compAddTwo, compAddOne),\
lodashComposed = lodash.flowRight && lodash.flowRight(compAddThree, compAddTwo, compAddOne);\
var _composed = _.compose(compAddThree, compAddTwo, compAddOne),\
lodashComposed = lodash.compose(compAddThree, compAddTwo, compAddOne);\
}\
if (typeof countBy != "undefined" || typeof omit != "undefined") {\
var wordToNumber = {\
@@ -453,8 +461,11 @@
if (typeof matches != "undefined") {\
var source = { "num": 9 };\
\
var _matcher = (_.matches || _.noop)(source),\
lodashMatcher = (lodash.matches || lodash.noop)(source);\
var _findWhere = _.findWhere || _.find,\
_matcher = (_.matches || _.createCallback || _.noop)(source);\
\
var lodashFindWhere = lodash.findWhere || lodash.find,\
lodashMatcher = (lodash.matches || lodash.createCallback || lodash.noop)(source);\
}\
if (typeof multiArrays != "undefined") {\
var twentyValues = belt.shuffle(belt.range(20)),\
@@ -560,11 +571,11 @@
suites.push(
Benchmark.Suite('`_.assign`')
.add(buildName, {
'fn': 'lodashAssign({}, { "a": 1, "b": 2, "c": 3 })',
'fn': 'lodashAssign({}, object)',
'teardown': 'function assign(){}'
})
.add(otherName, {
'fn': '_assign({}, { "a": 1, "b": 2, "c": 3 })',
'fn': '_assign({}, object)',
'teardown': 'function assign(){}'
})
);
@@ -572,11 +583,11 @@
suites.push(
Benchmark.Suite('`_.assign` with multiple sources')
.add(buildName, {
'fn': 'lodashAssign({}, { "a": 1, "b": 2 }, { "c": 3, "d": 4 })',
'fn': 'lodashAssign({}, object, object)',
'teardown': 'function assign(){}'
})
.add(otherName, {
'fn': '_assign({}, { "a": 1, "b": 2 }, { "c": 3, "d": 4 })',
'fn': '_assign({}, object, object)',
'teardown': 'function assign(){}'
})
);
@@ -634,13 +645,25 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.bindAll`')
Benchmark.Suite('`_.bindAll` iterating arguments')
.add(buildName, {
'fn': 'lodash.bindAll(bindAllObjects[++bindAllCount], funcNames)',
'fn': 'lodash.bindAll.apply(lodash, [bindAllObjects[++bindAllCount]].concat(funcNames))',
'teardown': 'function bindAll(){}'
})
.add(otherName, {
'fn': '_.bindAll(bindAllObjects[++bindAllCount], funcNames)',
'fn': '_.bindAll.apply(_, [bindAllObjects[++bindAllCount]].concat(funcNames))',
'teardown': 'function bindAll(){}'
})
);
suites.push(
Benchmark.Suite('`_.bindAll` iterating the `object`')
.add(buildName, {
'fn': 'lodash.bindAll(bindAllObjects[++bindAllCount])',
'teardown': 'function bindAll(){}'
})
.add(otherName, {
'fn': '_.bindAll(bindAllObjects[++bindAllCount])',
'teardown': 'function bindAll(){}'
})
);
@@ -683,6 +706,32 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.compose`')
.add(buildName, {
'fn': 'lodash.compose(compAddThree, compAddTwo, compAddOne)',
'teardown': 'function compose(){}'
})
.add(otherName, {
'fn': '_.compose(compAddThree, compAddTwo, compAddOne)',
'teardown': 'function compose(){}'
})
);
suites.push(
Benchmark.Suite('composed call')
.add(buildName, {
'fn': 'lodashComposed(0)',
'teardown': 'function compose(){}'
})
.add(otherName, {
'fn': '_composed(0)',
'teardown': 'function compose(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.countBy` with `callback` iterating an array')
.add(buildName, '\
@@ -783,6 +832,22 @@
)
);
suites.push(
Benchmark.Suite('`_.each` iterating an array with `thisArg` (slow path)')
.add(buildName, '\
var result = [];\
lodash.each(numbers, function(num, index) {\
result.push(num + this["key" + index]);\
}, object)'
)
.add(otherName, '\
var result = [];\
_.each(numbers, function(num, index) {\
result.push(num + this["key" + index]);\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.each` iterating an object')
.add(buildName, '\
@@ -845,6 +910,20 @@
)
);
suites.push(
Benchmark.Suite('`_.filter` iterating an array with `thisArg` (slow path)')
.add(buildName, '\
lodash.filter(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
.add(otherName, '\
_.filter(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.filter` iterating an object')
.add(buildName, '\
@@ -859,18 +938,6 @@
)
);
suites.push(
Benchmark.Suite('`_.filter` with `_.matches` shorthand')
.add(buildName, {
'fn': 'lodash.filter(objects, source)',
'teardown': 'function matches(){}'
})
.add(otherName, {
'fn': '_.filter(objects, source)',
'teardown': 'function matches(){}'
})
);
suites.push(
Benchmark.Suite('`_.filter` with `_.matches` predicate')
.add(buildName, {
@@ -914,17 +981,19 @@
);
// Avoid Underscore induced `OutOfMemoryError` in Rhino and Ringo.
suites.push(
Benchmark.Suite('`_.find` with `_.matches` shorthand')
.add(buildName, {
'fn': 'lodash.find(objects, source)',
'teardown': 'function matches(){}'
})
.add(otherName, {
'fn': '_.find(objects, source)',
'teardown': 'function matches(){}'
})
);
if (!isJava) {
suites.push(
Benchmark.Suite('`_.find` with `_.matches` shorthand')
.add(buildName, {
'fn': 'lodashFindWhere(objects, source)',
'teardown': 'function matches(){}'
})
.add(otherName, {
'fn': '_findWhere(objects, source)',
'teardown': 'function matches(){}'
})
);
}
/*--------------------------------------------------------------------------*/
@@ -940,60 +1009,32 @@
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.flattenDeep` nested arrays of numbers')
Benchmark.Suite('`_.flatten` nested arrays of numbers with `isDeep`')
.add(buildName, {
'fn': 'lodash.flattenDeep(nestedNumbers)',
'fn': 'lodash.flatten(nestedNumbers, lodashFlattenDeep)',
'teardown': 'function flatten(){}'
})
.add(otherName, {
'fn': '_.flattenDeep(nestedNumbers)',
'fn': '_.flatten(nestedNumbers, _flattenDeep)',
'teardown': 'function flatten(){}'
})
);
suites.push(
Benchmark.Suite('`_.flattenDeep` nest arrays of objects')
Benchmark.Suite('`_.flatten` nest arrays of objects with `isDeep`')
.add(buildName, {
'fn': 'lodash.flattenDeep(nestedObjects)',
'fn': 'lodash.flatten(nestedObjects, lodashFlattenDeep)',
'teardown': 'function flatten(){}'
})
.add(otherName, {
'fn': '_.flattenDeep(nestedObjects)',
'fn': '_.flatten(nestedObjects, _flattenDeep)',
'teardown': 'function flatten(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.flowRight`')
.add(buildName, {
'fn': 'lodash.flowRight(compAddThree, compAddTwo, compAddOne)',
'teardown': 'function flowRight(){}'
})
.add(otherName, {
'fn': '_.flowRight(compAddThree, compAddTwo, compAddOne)',
'teardown': 'function flowRight(){}'
})
);
suites.push(
Benchmark.Suite('composed call')
.add(buildName, {
'fn': 'lodashComposed(0)',
'teardown': 'function flowRight(){}'
})
.add(otherName, {
'fn': '_composed(0)',
'teardown': 'function flowRight(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.functions`')
.add(buildName, '\
@@ -1045,37 +1086,73 @@
suites.push(
Benchmark.Suite('`_.includes` searching an array')
.add(buildName, '\
lodash.includes(numbers, limit - 1)'
lodash.include(numbers, limit - 1)'
)
.add(otherName, '\
_.includes(numbers, limit - 1)'
_.include(numbers, limit - 1)'
)
);
suites.push(
Benchmark.Suite('`_.includes` searching an object')
.add(buildName, '\
lodash.includes(object, limit - 1)'
lodash.include(object, limit - 1)'
)
.add(otherName, '\
_.includes(object, limit - 1)'
_.include(object, limit - 1)'
)
);
if (lodash.includes('ab', 'ab') && _.includes('ab', 'ab')) {
if (lodash.include('ab', 'ab') && _.include('ab', 'ab')) {
suites.push(
Benchmark.Suite('`_.includes` searching a string')
.add(buildName, '\
lodash.includes(strNumbers, "," + (limit - 1))'
lodash.include(strNumbers, "," + (limit - 1))'
)
.add(otherName, '\
_.includes(strNumbers, "," + (limit - 1))'
_.include(strNumbers, "," + (limit - 1))'
)
);
}
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.indexBy` with `callback` iterating an array')
.add(buildName, '\
lodash.indexBy(numbers, function(num) { return num >> 1; })'
)
.add(otherName, '\
_.indexBy(numbers, function(num) { return num >> 1; })'
)
);
suites.push(
Benchmark.Suite('`_.indexBy` with `property` name iterating an array')
.add(buildName, {
'fn': 'lodash.indexBy(words, "length")',
'teardown': 'function countBy(){}'
})
.add(otherName, {
'fn': '_.indexBy(words, "length")',
'teardown': 'function countBy(){}'
})
);
suites.push(
Benchmark.Suite('`_.indexBy` with `callback` iterating an object')
.add(buildName, {
'fn': 'lodash.indexBy(wordToNumber, function(num) { return num >> 1; })',
'teardown': 'function countBy(){}'
})
.add(otherName, {
'fn': '_.indexBy(wordToNumber, function(num) { return num >> 1; })',
'teardown': 'function countBy(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.indexOf`')
.add(buildName, {
@@ -1088,6 +1165,18 @@
})
);
suites.push(
Benchmark.Suite('`_.indexOf` performing a binary search')
.add(buildName, {
'fn': 'lodash.indexOf(hundredSortedValues, 99, true)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.indexOf(hundredSortedValues, 99, true)',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
@@ -1127,42 +1216,42 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.invokeMap` iterating an array')
Benchmark.Suite('`_.invoke` iterating an array')
.add(buildName, '\
lodash.invokeMap(numbers, "toFixed")'
lodash.invoke(numbers, "toFixed")'
)
.add(otherName, '\
_.invokeMap(numbers, "toFixed")'
_.invoke(numbers, "toFixed")'
)
);
suites.push(
Benchmark.Suite('`_.invokeMap` with arguments iterating an array')
Benchmark.Suite('`_.invoke` with arguments iterating an array')
.add(buildName, '\
lodash.invokeMap(numbers, "toFixed", 1)'
lodash.invoke(numbers, "toFixed", 1)'
)
.add(otherName, '\
_.invokeMap(numbers, "toFixed", 1)'
_.invoke(numbers, "toFixed", 1)'
)
);
suites.push(
Benchmark.Suite('`_.invokeMap` with a function for `path` iterating an array')
Benchmark.Suite('`_.invoke` with a function for `path` iterating an array')
.add(buildName, '\
lodash.invokeMap(numbers, Number.prototype.toFixed, 1)'
lodash.invoke(numbers, Number.prototype.toFixed, 1)'
)
.add(otherName, '\
_.invokeMap(numbers, Number.prototype.toFixed, 1)'
_.invoke(numbers, Number.prototype.toFixed, 1)'
)
);
suites.push(
Benchmark.Suite('`_.invokeMap` iterating an object')
Benchmark.Suite('`_.invoke` iterating an object')
.add(buildName, '\
lodash.invokeMap(object, "toFixed", 1)'
lodash.invoke(object, "toFixed", 1)'
)
.add(otherName, '\
_.invokeMap(object, "toFixed", 1)'
_.invoke(object, "toFixed", 1)'
)
);
@@ -1324,6 +1413,18 @@
})
);
suites.push(
Benchmark.Suite('`_.lastIndexOf` performing a binary search')
.add(buildName, {
'fn': 'lodash.lastIndexOf(hundredSortedValues, 0, true)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.lastIndexOf(hundredSortedValues, 0, true)',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
@@ -1340,6 +1441,20 @@
)
);
suites.push(
Benchmark.Suite('`_.map` with `thisArg` iterating an array (slow path)')
.add(buildName, '\
lodash.map(objects, function(value, index) {\
return this["key" + index] + value.num;\
}, object)'
)
.add(otherName, '\
_.map(objects, function(value, index) {\
return this["key" + index] + value.num;\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.map` iterating an object')
.add(buildName, '\
@@ -1354,16 +1469,6 @@
)
);
suites.push(
Benchmark.Suite('`_.map` with `_.property` shorthand')
.add(buildName, '\
lodash.map(objects, "num")'
)
.add(otherName, '\
_.map(objects, "num")'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
@@ -1414,6 +1519,18 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.pairs`')
.add(buildName, '\
lodash.pairs(object)'
)
.add(otherName, '\
_.pairs(object)'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.partial` (slow path)')
.add(buildName, {
@@ -1454,6 +1571,20 @@
)
);
suites.push(
Benchmark.Suite('`_.partition` iterating an array with `thisArg` (slow path)')
.add(buildName, '\
lodash.partition(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
.add(otherName, '\
_.partition(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.partition` iterating an object')
.add(buildName, '\
@@ -1482,6 +1613,18 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.pluck`')
.add(buildName, '\
lodash.pluck(objects, "num")'
)
.add(otherName, '\
_.pluck(objects, "num")'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.reduce` iterating an array')
.add(buildName, '\
@@ -1564,6 +1707,20 @@
)
);
suites.push(
Benchmark.Suite('`_.reject` iterating an array with `thisArg` (slow path)')
.add(buildName, '\
lodash.reject(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
.add(otherName, '\
_.reject(numbers, function(num, index) {\
return this["key" + index] % 2;\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.reject` iterating an object')
.add(buildName, '\
@@ -1581,12 +1738,12 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sampleSize`')
Benchmark.Suite('`_.sample` with an `n`')
.add(buildName, '\
lodash.sampleSize(numbers, limit / 2)'
lodash.sample(numbers, limit / 2)'
)
.add(otherName, '\
_.sampleSize(numbers, limit / 2)'
_.sample(numbers, limit / 2)'
)
);
@@ -1630,6 +1787,20 @@
)
);
suites.push(
Benchmark.Suite('`_.some` with `thisArg` iterating an array (slow path)')
.add(buildName, '\
lodash.some(objects, function(value, index) {\
return this["key" + index] == (limit - 1);\
}, object)'
)
.add(otherName, '\
_.some(objects, function(value, index) {\
return this["key" + index] == (limit - 1);\
}, object)'
)
);
suites.push(
Benchmark.Suite('`_.some` iterating an object')
.add(buildName, '\
@@ -1656,6 +1827,16 @@
)
);
suites.push(
Benchmark.Suite('`_.sortBy` with `callback` and `thisArg` (slow path)')
.add(buildName, '\
lodash.sortBy(numbers, function(num) { return this.sin(num); }, Math)'
)
.add(otherName, '\
_.sortBy(numbers, function(num) { return this.sin(num); }, Math)'
)
);
suites.push(
Benchmark.Suite('`_.sortBy` with `property` name')
.add(buildName, {
@@ -1680,20 +1861,18 @@
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sortedIndexBy`')
Benchmark.Suite('`_.sortedIndex` with `callback`')
.add(buildName, {
'fn': '\
lodash.sortedIndexBy(words, "twenty-five", function(value) {\
lodash.sortedIndex(words, "twenty-five", function(value) {\
return wordToNumber[value];\
})',
'teardown': 'function countBy(){}'
})
.add(otherName, {
'fn': '\
_.sortedIndexBy(words, "twenty-five", function(value) {\
_.sortedIndex(words, "twenty-five", function(value) {\
return wordToNumber[value];\
})',
'teardown': 'function countBy(){}'
@@ -1702,34 +1881,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sortedIndexOf`')
.add(buildName, {
'fn': 'lodash.sortedIndexOf(hundredSortedValues, 99)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.sortedIndexOf(hundredSortedValues, 99)',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sortedLastIndexOf`')
.add(buildName, {
'fn': 'lodash.sortedLastIndexOf(hundredSortedValues, 0)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.sortedLastIndexOf(hundredSortedValues, 0)',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sum`')
.add(buildName, '\
@@ -1792,6 +1943,18 @@
)
);
suites.push(
Benchmark.Suite('`_.times` with `thisArg` (slow path)')
.add(buildName, '\
var result = [];\
lodash.times(limit, function(n) { result.push(this.sin(n)); }, Math)'
)
.add(otherName, '\
var result = [];\
_.times(limit, function(n) { result.push(this.sin(n)); }, Math)'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
@@ -1816,18 +1979,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.toPairs`')
.add(buildName, '\
lodash.toPairs(object)'
)
.add(otherName, '\
_.toPairs(object)'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.unescape` string without html entities')
.add(buildName, '\
@@ -1884,6 +2035,20 @@
)
);
suites.push(
Benchmark.Suite('`_.uniq` with `callback`')
.add(buildName, '\
lodash.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\
})'
)
.add(otherName, '\
_.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\
})'
)
);
suites.push(
Benchmark.Suite('`_.uniq` iterating an array of 200 elements')
.add(buildName, {
@@ -1898,22 +2063,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.uniqBy`')
.add(buildName, '\
lodash.uniqBy(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\
})'
)
.add(otherName, '\
_.uniqBy(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\
})'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.values`')
.add(buildName, '\
@@ -1926,6 +2075,20 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.where`')
.add(buildName, {
'fn': 'lodash.where(objects, source)',
'teardown': 'function matches(){}'
})
.add(otherName, {
'fn': '_.where(objects, source)',
'teardown': 'function matches(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.without`')
.add(buildName, '\

14
perf/run-perf.sh Executable file
View File

@@ -0,0 +1,14 @@
cd "$(dirname "$0")"
echo "Running performance suite in node..."
node perf.js ../lodash.js && node perf.js ../lodash.min.js
for cmd in rhino "rhino -require" narwhal ringo phantomjs; do
echo ""
echo "Running performance suite in $cmd..."
$cmd perf.js ../lodash.src.js
done
echo ""
echo "Running performance suite in a browser..."
open index.html

157
test/asset/set.js Normal file
View File

@@ -0,0 +1,157 @@
;(function() {
/** Used to determine if values are of the language type Object. */
var objectTypes = {
'function': true,
'object': true
};
/** Used as the `Set#toString` return value. */
var nativeString = String(Object.prototype.toString).replace(/toString/g, 'Set');
/** Detect free variable `exports`. */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect free variable `global` from Node.js. */
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
/** Detect free variable `self`. */
var freeSelf = objectTypes[typeof self] && self && self.Object && self;
/** Detect free variable `window`. */
var freeWindow = objectTypes[typeof window] && window && window.Object && window;
/**
* Used as a reference to the global object.
*
* The `this` value is used if it is the global object to avoid Greasemonkey's
* restricted `window` object, otherwise the `window` object is used.
*/
var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
/*--------------------------------------------------------------------------*/
/**
* Installs `Set` on the given `context` object.
*
* @memberOf exports
* @param {Object} context The context object.
*/
function runInContext(context) {
/**
* Creates a `Set` object.
*/
function Set() {
this.__cache__ = {};
}
/**
* Gets the index at which the first occurrence of `value` is found using
* strict equality for comparisons, i.e. `===`.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @returns {number} Returns the index of the matched value or `-1`.
*/
function indexOf(array, value) {
var index = -1,
length = array.length;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* Checks if `value` is in the set.
*
* @memberOf Set
* @param {*} value The value to search for.
* @returns {boolean} Returns `true` if `value` is found, else `false`.
*/
function has(value) {
var type = typeof value,
cache = this.__cache__;
if (type == 'boolean' || value == null) {
return cache[value] || false;
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : '_' + value;
cache = (cache = cache[type]) && cache[key];
return type == 'object'
? (cache && indexOf(cache, value) > -1 ? true : false)
: (cache || false);
}
/**
* Adds `value` to the set.
*
* @memberOf Set
* @param {*} value The value to add.
*/
function add(value) {
var cache = this.__cache__,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : '_' + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
var array = typeCache[key];
if (array) {
array.push(value);
} else {
typeCache[key] = [value];
}
} else {
typeCache[key] = true;
}
}
}
/**
* Produces the `toString` result of `Set`.
*
* @static
* @memberOf Set
* @returns {string} Returns the string result.
*/
function toString() {
return nativeString;
}
Set.toString = toString;
Set.prototype.add = add;
Set.prototype.has = has;
if (!root.Set) {
context.Set = Set;
}
}
/*--------------------------------------------------------------------------*/
if (freeExports) {
freeExports.runInContext = runInContext;
} else {
runInContext(root);
}
}.call(this));

View File

@@ -15,8 +15,27 @@
/*--------------------------------------------------------------------------*/
/**
* Registers an event listener on an element.
*
* @private
* @param {Element} element The element.
* @param {string} eventName The name of the event.
* @param {Function} handler The event handler.
* @returns {Element} The element.
*/
function addListener(element, eventName, handler) {
if (typeof element.addEventListener != 'undefined') {
element.addEventListener(eventName, handler, false);
} else if (typeof element.attachEvent != 'undefined') {
element.attachEvent('on' + eventName, handler);
}
}
/*--------------------------------------------------------------------------*/
// Initialize controls.
addEventListener('load', function() {
addListener(window, 'load', function() {
function eventHandler(event) {
var buildIndex = buildList.selectedIndex,
loaderIndex = loaderList.selectedIndex,
@@ -40,15 +59,17 @@
setTimeout(init, 15);
return;
}
toolbar.insertBefore(span2, toolbar.lastChild);
toolbar.insertBefore(span1, span2);
toolbar.appendChild(span1);
toolbar.appendChild(span2);
buildList.selectedIndex = (function() {
switch (build) {
case 'lodash': return 1;
case 'lodash-core-dev': return 2;
case 'lodash-core': return 3;
case 'lodash-dev':
case 'lodash-compat': return 1;
case 'lodash-modern-dev': return 2;
case 'lodash-modern': return 3;
case 'lodash-custom-dev': return 4;
case 'lodash-custom': return 5;
case 'lodash-compat-dev':
case null: return 0;
}
return -1;
@@ -65,21 +86,25 @@
return -1;
}());
buildList.addEventListener('change', eventHandler);
loaderList.addEventListener('change', eventHandler);
addListener(buildList, 'change', eventHandler);
addListener(loaderList, 'change', eventHandler);
}
var span1 = document.createElement('span');
span1.style.cssText = 'float:right';
span1.innerHTML =
'<label for="qunit-build">Build: </label>' +
'<select id="qunit-build">' +
'<option value="lodash-dev">lodash (development)</option>' +
'<option value="lodash">lodash (production)</option>' +
'<option value="lodash-core-dev">lodash-core (development)</option>' +
'<option value="lodash-core">lodash-core (production)</option>' +
'<option value="lodash-compat-dev">lodash (compat development)</option>' +
'<option value="lodash-compat">lodash (compat production)</option>' +
'<option value="lodash-modern-dev">lodash (modern development)</option>' +
'<option value="lodash-modern">lodash (modern production)</option>' +
'<option value="lodash-custom-dev">lodash (custom development)</option>' +
'<option value="lodash-custom">lodash (custom production)</option>' +
'</select>';
var span2 = document.createElement('span');
span2.style.cssText = 'float:right';
span2.innerHTML =
'<label for="qunit-loader">Loader: </label>' +
'<select id="qunit-loader">' +
@@ -89,12 +114,6 @@
'<option value="requirejs">RequireJS</option>' +
'</select>';
span1.style.cssText =
span2.style.cssText = 'display:inline-block;float:right;line-height:2.1em;margin-left:1em;margin-top:0;';
span1.firstChild.style.cssText =
span2.firstChild.style.cssText = 'display:inline-block;margin-right:.5em;';
var buildList = span1.lastChild,
loaderList = span2.lastChild;
@@ -105,15 +124,29 @@
init();
});
// Used to indicate testing a foreign file.
ui.isForeign = RegExp('^(\\w+:)?//').test(build);
// Used to indicate testing a modularized build.
ui.isModularize = /\b(?:amd|commonjs|es6?|node|npm|(index|main)\.js)\b/.test([location.pathname, location.search]);
// Used to indicate testing in Sauce Labs' automated test cloud.
ui.isSauceLabs = location.port == '9001';
// Used to indicate that lodash is in strict mode.
ui.isStrict = /\bes6?\b/.test([location.pathname, location.search]);
// The lodash build file path.
ui.buildPath = (function() {
var result;
switch (build) {
case 'lodash': result = 'dist/lodash.min.js'; break;
case 'lodash-core-dev': result = 'dist/lodash.core.js'; break;
case 'lodash-core': result = 'dist/lodash.core.min.js'; break;
case null: build = 'lodash-dev';
case 'lodash-dev': result = 'lodash.js'; break;
case 'lodash-compat': result = 'lodash.compat.min.js'; break;
case 'lodash-modern-dev': result = 'lodash.js'; break;
case 'lodash-modern': result = 'lodash.min.js'; break;
case 'lodash-custom-dev': result = 'lodash.custom.js'; break;
case 'lodash-custom': result = 'lodash.custom.min.js'; break;
case null: build = 'lodash-compat-dev';
case 'lodash-compat-dev': result = 'lodash.src.js'; break;
default: return build;
}
return basePath + result;
@@ -132,21 +165,6 @@
return basePath + result;
}());
// Used to indicate testing a core build.
ui.isCore = /\bcore(\.min)?\.js\b/.test(ui.buildPath);
// Used to indicate testing a foreign file.
ui.isForeign = RegExp('^(\\w+:)?//').test(build);
// Used to indicate testing a modularized build.
ui.isModularize = /\b(?:amd|commonjs|es|node|npm|(index|main)\.js)\b/.test([location.pathname, location.search]);
// Used to indicate testing in Sauce Labs' automated test cloud.
ui.isSauceLabs = location.port == '9001';
// Used to indicate that lodash is in strict mode.
ui.isStrict = /\bes\b/.test([location.pathname, location.search]);
ui.urlParams = { 'build': build, 'loader': loader };
ui.timing = { 'loadEventEnd': 0 };

102
test/asset/weakmap.js Normal file
View File

@@ -0,0 +1,102 @@
;(function() {
/** Used to determine if values are of the language type Object. */
var objectTypes = {
'function': true,
'object': true
};
/** Used as the `WeakMap#toString` return value. */
var nativeString = String(Object.prototype.toString).replace(/toString/g, 'WeakMap');
/** Detect free variable `exports`. */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect free variable `global` from Node.js. */
var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
/** Detect free variable `self`. */
var freeSelf = objectTypes[typeof self] && self && self.Object && self;
/** Detect free variable `window`. */
var freeWindow = objectTypes[typeof window] && window && window.Object && window;
/**
* Used as a reference to the global object.
*
* The `this` value is used if it is the global object to avoid Greasemonkey's
* restricted `window` object, otherwise the `window` object is used.
*/
var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
/*--------------------------------------------------------------------------*/
/**
* Installs `WeakMap` on the given `context` object.
*
* @memberOf exports
* @param {Object} context The context object.
*/
function runInContext(context) {
/**
* Creates a `WeakMap` object.
*/
function WeakMap() {
// No operation performed.
}
/**
* Gets the value associated with the given key.
*
* @memberOf WeakMap
* @param {Object} key The key object.
* @returns {*} Returns the associated value, else `undefined`.
*/
function get(key) {
return key.__weakmap__;
}
/**
* Sets a value for the given key.
*
* @memberOf WeakMap
* @param {Object} key The key object.
* @param {*} value The value to set.
*/
function set(key, value) {
key.__weakmap__ = value;
return this;
}
/**
* Produces the `toString` result of `WeakMap`.
*
* @static
* @memberOf WeakMap
* @returns {string} Returns the string result.
*/
function toString() {
return nativeString;
}
WeakMap.toString = toString;
WeakMap.prototype.get = get;
WeakMap.prototype.set = set;
if (!root.WeakMap) {
context.WeakMap = WeakMap;
}
}
/*--------------------------------------------------------------------------*/
if (freeExports) {
freeExports.runInContext = runInContext;
} else {
runInContext(root);
}
}.call(this));

View File

@@ -1,17 +1,12 @@
'use strict';
self.console || (self.console = { 'log': function() {} });
addEventListener('message', function(e) {
if (e.data) {
try {
importScripts('../' + e.data);
} catch (e) {
var lineNumber = e.lineNumber,
message = (lineNumber == null ? '' : (lineNumber + ': ')) + e.message;
self._ = { 'VERSION': message };
} catch(e) {
self._ = { 'VERSION': e.message };
}
postMessage(_.VERSION);
}
});
}, false);

View File

@@ -22,69 +22,27 @@
<script src="../vendor/json-js/json2.js"></script>
<script src="../node_modules/platform/platform.js"></script>
<script src="./asset/test-ui.js"></script>
<script src="../lodash.js"></script>
<script src="../lodash.src.js"></script>
<script>
QUnit.config.asyncRetries = 10;
QUnit.config.hidepassed = true;
var mixinPrereqs = (function() {
var aliasToReal = {
'indexBy': 'keyBy',
'invoke': 'invokeMap'
};
var keyMap = {
'rest': 'tail'
};
var lodash = _.noConflict();
return function(_) {
lodash(_)
.defaultsDeep({ 'templateSettings': lodash.templateSettings })
.mixin(lodash.pick(lodash, lodash.difference([
'countBy',
'debounce',
'difference',
'find',
'findIndex',
'findLastIndex',
'groupBy',
'includes',
'invert',
'invokeMap',
'keyBy',
'omit',
'partition',
'reduceRight',
'reject',
'sample',
'without'
], lodash.functions(_))))
.value();
lodash.forOwn(keyMap, function(realName, otherName) {
_[otherName] = lodash[realName];
_.prototype[otherName] = lodash.prototype[realName];
_.mixin({
'debounce': _.debounce || lodash.debounce,
'defer': _.defer || lodash.defer,
'pluck': _.pluck || lodash.pluck
});
lodash.forOwn(aliasToReal, function(realName, alias) {
_[alias] = _[realName];
_.prototype[alias] = _.prototype[realName];
});
return _;
};
}());
// Load prerequisite scripts.
document.write(ui.urlParams.loader == 'none'
? '<script src="' + ui.buildPath + '"><\/script>'
: '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
);
</script>
<script>
if (ui.urlParams.loader == 'none') {
mixinPrereqs(_);
document.write([
QUnit.config.asyncRetries = 10;
QUnit.config.hidepassed = true;
// Load test scripts.
document.write(ui.urlParams.loader != 'none'
? '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
: ([
'<script src="' + ui.buildPath + '"><\/script>',
'<script src="../node_modules/jquery/dist/jquery.js"><\/script>',
'<script src="../vendor/backbone/backbone.js"><\/script>',
'<script src="../vendor/backbone/test/setup/dom-setup.js"><\/script>',
@@ -96,8 +54,8 @@
'<script src="../vendor/backbone/test/router.js"><\/script>',
'<script src="../vendor/backbone/test/view.js"><\/script>',
'<script src="../vendor/backbone/test/sync.js"><\/script>'
].join('\n'));
}
].join('\n'))
);
</script>
<script>
(function() {
@@ -105,6 +63,7 @@
curl.config({ 'apiName': 'require' });
}
if (!window.require) {
mixinPrereqs(_);
return;
}
var reBasename = /[\w.-]+$/,
@@ -148,20 +107,24 @@
QUnit.config.autostart = false;
require(getConfig(), ['underscore'], function(lodash) {
_ = mixinPrereqs(lodash);
require(getConfig(), ['backbone'], function() {
require(getConfig(), [
'test/setup/dom-setup',
'test/setup/environment',
'test/noconflict',
'test/events',
'test/model',
'test/collection',
'test/router',
'test/view',
'test/sync'
], QUnit.start);
require(getConfig(), ['underscore', 'backbone'], function(lodash) {
mixinPrereqs(lodash);
if (ui.isModularize) {
window._ = lodash;
}
require(getConfig(), [
'test/setup/dom-setup',
'test/setup/environment',
'test/noconflict',
'test/events',
'test/model',
'test/collection',
'test/router',
'test/view',
'test/sync'
], function() {
QUnit.start();
});
});
}());

View File

@@ -1,41 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>lodash-fp Test Suite</title>
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
</head>
<body>
<script>
// Avoid reporting tests to Sauce Labs when script errors occur.
if (location.port == '9001') {
window.onerror = function(message) {
if (window.QUnit) {
QUnit.config.done.length = 0;
}
global_test_results = { 'message': message };
};
}
</script>
<script src="../lodash.js"></script>
<script src="../dist/lodash.fp.js"></script>
<script src="../dist/mapping.fp.js"></script>
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
<script src="../node_modules/qunit-extras/qunit-extras.js"></script>
<script src="../node_modules/platform/platform.js"></script>
<script src="./test-fp.js"></script>
<div id="qunit"></div>
<script>
// Set a more readable browser name.
window.onload = function() {
var timeoutId = setInterval(function() {
var ua = document.getElementById('qunit-userAgent');
if (ua) {
ua.innerHTML = platform;
clearInterval(timeoutId);
}
}, 16);
};
</script>
</body>
</html>

View File

@@ -5,7 +5,7 @@
<title>lodash Test Suite</title>
<link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
<style>
#exports, #module {
#exports {
display: none;
}
</style>
@@ -22,33 +22,35 @@
};
}
</script>
<script src="../node_modules/lodash/lodash.js"></script>
<script>var lodashStable = _.noConflict();</script>
<script src="../node_modules/qunitjs/qunit/qunit.js"></script>
<script src="../node_modules/qunit-extras/qunit-extras.js"></script>
<script src="../node_modules/platform/platform.js"></script>
<script src="./asset/set.js"></script>
<script src="./asset/weakmap.js"></script>
<script src="./asset/test-ui.js"></script>
<div id="qunit"></div>
<div id="exports"></div>
<div id="module"></div>
<script>
function setProperty(object, key, value) {
try {
Object.defineProperty(object, key, {
'configurable': true,
'enumerable': false,
'writable': true,
'value': value
});
} catch (e) {
object[key] = value;
}
return object;
}
var setProperty = (function() {
var _defineProperty = Object.defineProperty;
return function(object, key, value) {
try {
_defineProperty(object, key, {
'configurable': true,
'enumerable': false,
'writable': true,
'value': value
});
} catch(e) {
object[key] = value;
}
};
}());
function addBizarroMethods() {
var funcProto = Function.prototype,
objectProto = Object.prototype;
objectProto = Object.prototype,
stringProto = String.prototype;
var hasOwnProperty = objectProto.hasOwnProperty,
fnToString = funcProto.toString,
@@ -62,11 +64,9 @@
return value;
};
}
function createToString(funcName) {
return constant(nativeString.replace(reToString, funcName));
}
// Allow bypassing native checks.
setProperty(funcProto, 'toString', (function() {
function wrapper() {
@@ -82,42 +82,29 @@
funcProto._method = noop;
// Set bad shims.
setProperty(Object, '_create', Object.create);
setProperty(Object, 'create', undefined);
setProperty(Array, '_isArray', Array.isArray);
setProperty(Array, 'isArray', noop);
setProperty(Object, '_getOwnPropertySymbols', Object.getOwnPropertySymbols);
setProperty(Object, 'getOwnPropertySymbols', undefined);
setProperty(Date, '_now', Date.now);
setProperty(Date, 'now', noop);
setProperty(Object, '_keys', Object.keys);
setProperty(Object, 'keys', noop);
setProperty(objectProto, '_propertyIsEnumerable', propertyIsEnumerable);
setProperty(objectProto, 'propertyIsEnumerable', function(key) {
return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnumerable.call(this, key);
if (key == '1' && this && typeof this == 'object' &&
hasOwnProperty.call(this, 'callee') &&
!propertyIsEnumerable.call(this, 'callee') &&
this.length === 2 && this[0] === 1 && this[1] === 0) {
throw new Error;
}
return propertyIsEnumerable.call(this, key);
});
setProperty(window, '_Map', window.Map);
if (_Map) {
setProperty(window, 'Map', (function(Map) {
var count = 0;
return function() {
if (count++) {
return new Map;
}
var result = {};
setProperty(window, 'Map', Map);
return result;
};
}(_Map)));
setProperty(Map, 'toString', createToString('Map'));
}
setProperty(window, '_Promise', window.Promise);
setProperty(window, 'Promise', noop);
setProperty(window, '_Set', window.Set);
setProperty(window, 'Set', noop);
setProperty(window, '_Symbol', window.Symbol);
setProperty(window, 'Symbol', undefined);
setProperty(window, '_WeakMap', window.WeakMap);
setProperty(window, 'WeakMap', noop);
@@ -132,58 +119,46 @@
function removeBizarroMethods() {
var funcProto = Function.prototype,
objectProto = Object.prototype;
objectProto = Object.prototype,
stringProto = String.prototype;
setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable);
if (Object._create) {
Object.create = Object._create;
if (Array._isArray) {
setProperty(Array, 'isArray', Array._isArray);
} else {
delete Object.create;
delete Array.isArray;
}
if (Object._getOwnPropertySymbols) {
Object.getOwnPropertySymbols = Object._getOwnPropertySymbols;
if (Date._now) {
setProperty(Date, 'now', Date._now);
} else {
delete Object.getOwnPropertySymbols;
delete Date.now;
}
if (_Map) {
Map = _Map;
if (Object._keys) {
setProperty(Object, 'keys', Object._keys);
} else {
setProperty(window, 'Map', undefined);
delete Object.keys;
}
if (_Promise) {
Promise = _Promise;
} else {
setProperty(window, 'Promise', undefined);
}
if (_Set) {
if (window._Set) {
Set = _Set;
} else {
setProperty(window, 'Set', undefined);
}
if (_Symbol) {
Symbol = _Symbol;
}
if (_WeakMap) {
WeakMap = _WeakMap;
} else {
setProperty(window, 'WeakMap', undefined);
}
setProperty(window, '_Map', undefined);
setProperty(window, '_Promise', undefined);
setProperty(window, '_Set', undefined);
setProperty(window, '_Symbol', undefined);
if (window._WeakMap) {
WeakMap = _WeakMap;
}
setProperty(window, '_WeakMap', undefined);
setProperty(window, 'WinRTError', undefined);
setProperty(window, 'exports', document.getElementById('exports'));
setProperty(window, 'exports', undefined);
setProperty(window, 'global', undefined);
setProperty(window, 'module', document.getElementById('module'));
setProperty(window, 'module', undefined);
setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable);
delete Array._isArray;
delete Date._now;
delete Object._keys;
delete funcProto._method;
delete Object._create;
delete Object._getOwnPropertySymbols;
delete objectProto._propertyIsEnumerable;
}
@@ -291,17 +266,20 @@
underscoreModule = underscore.result(underscore, 'noConflict') || underscore;
underscoreModule.moduleName = 'underscore';
}
window._ = lodash;
if (ui.isModularize) {
window._ = lodash;
}
if (ui.isModularize) {
require(getConfig(), [
'lodash/_baseEach',
'lodash/_isIndex',
'lodash/_isIterateeCall'
], function(baseEach, isIndex, isIterateeCall) {
'lodash/internal/baseEach',
'lodash/internal/isIndex',
'lodash/internal/isIterateeCall',
'lodash/internal/isLength'
], function(baseEach, isIndex, isIterateeCall, isLength) {
lodash._baseEach = baseEach;
lodash._isIndex = isIndex;
lodash._isIterateeCall = isIterateeCall;
lodash._isLength = isLength;
loadTests();
});
} else {

View File

@@ -1,27 +0,0 @@
#!/usr/bin/env node
'use strict';
var _ = require('../lodash'),
fs = require('fs'),
path = require('path');
var args = (args = process.argv)
.slice((args[0] === process.execPath || args[0] === 'node') ? 2 : 0);
var filePath = path.resolve(args[1]),
reLine = /.*/gm;
var pattern = (function() {
var result = args[0],
delimiter = result.charAt(0),
lastIndex = result.lastIndexOf(delimiter);
return RegExp(result.slice(1, lastIndex), result.slice(lastIndex + 1));
}());
/*----------------------------------------------------------------------------*/
fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8').replace(pattern, function(match) {
var snippet = _.slice(arguments, -3, -2)[0];
return match.replace(snippet, snippet.replace(reLine, ''));
}));

14
test/run-test.sh Normal file
View File

@@ -0,0 +1,14 @@
cd "$(dirname "$0")"
echo "Testing in node..."
node test.js ../lodash.src.js
for cmd in rhino "rhino -require" ringo phantomjs; do
echo ""
echo "Testing in $cmd..."
$cmd test.js ../lodash.src.js
done
echo ""
echo "Testing in a browser..."
open index.html

View File

@@ -4,6 +4,11 @@
/** Environment shortcut. */
var env = process.env;
if (env.TRAVIS_SECURE_ENV_VARS == 'false') {
console.log('Skipping Sauce Labs jobs; secure environment variables are unavailable');
process.exit(0);
}
/** Load Node.js modules. */
var EventEmitter = require('events').EventEmitter,
http = require('http'),
@@ -12,7 +17,7 @@ var EventEmitter = require('events').EventEmitter,
util = require('util');
/** Load other modules. */
var _ = require('../lodash.js'),
var _ = require('../lodash.src.js'),
chalk = require('chalk'),
ecstatic = require('ecstatic'),
request = require('request'),
@@ -92,23 +97,31 @@ var browserNameMap = {
'googlechrome': 'Chrome',
'iehta': 'Internet Explorer',
'ipad': 'iPad',
'iphone': 'iPhone',
'microsoftedge': 'Edge'
'iphone': 'iPhone'
};
/** List of platforms to load the runner on. */
var platforms = [
['Linux', 'android', '5.1'],
['Windows 10', 'chrome', '54'],
['Windows 10', 'chrome', '53'],
['Windows 10', 'firefox', '50'],
['Windows 10', 'firefox', '49'],
['Windows 10', 'microsoftedge', '14'],
['Windows 10', 'internet explorer', '11'],
['Linux', 'android', '5.0'],
['Linux', 'android', '4.4'],
['Linux', 'android', '4.0'],
['Windows 8.1', 'firefox', '38'],
['Windows 8.1', 'firefox', '37'],
['Windows 8.1', 'firefox', '20'],
['Windows 8.1', 'chrome', '43'],
['Windows 8.1', 'chrome', '42'],
['Windows 8.1', 'internet explorer', '11'],
['Windows 8', 'internet explorer', '10'],
['Windows 7', 'internet explorer', '9'],
['macOS 10.12', 'safari', '10'],
['OS X 10.11', 'safari', '9']
['Windows 7', 'internet explorer', '8'],
['Windows XP', 'internet explorer', '7'],
['Windows XP', 'internet explorer', '6'],
['OS X 10.9', 'ipad', '8.1'],
['OS X 10.6', 'ipad', '4'],
['OS X 10.10', 'safari', '8'],
['OS X 10.9', 'safari', '7'],
['OS X 10.8', 'safari', '6'],
['OS X 10.6', 'safari', '5']
];
/** Used to tailor the `platforms` array. */
@@ -119,7 +132,7 @@ var isAMD = _.includes(tags, 'amd'),
// The platforms to test IE compatibility modes.
if (compatMode) {
platforms = [
['Windows 10', 'internet explorer', '11'],
['Windows 8.1', 'internet explorer', '11'],
['Windows 8', 'internet explorer', '10'],
['Windows 7', 'internet explorer', '9'],
['Windows 7', 'internet explorer', '8']
@@ -208,7 +221,18 @@ if (tunneled) {
* @returns {string} Returns the formal browser name.
*/
function browserName(identifier) {
return browserNameMap[identifier] || _.startCase(identifier);
return browserNameMap[identifier] || capitalizeWords(identifier);
}
/**
* Capitalizes the first character of each word in `string`.
*
* @private
* @param {string} string The string to augment.
* @returns {string} Returns the augmented string.
*/
function capitalizeWords(string) {
return _.map(string.split(' '), _.capitalize).join(' ');
}
/**
@@ -252,7 +276,7 @@ function isJobId(value) {
*/
function logInline(text) {
var blankLine = _.repeat(' ', _.size(prevLine));
prevLine = text = _.truncate(text, { 'length': 40 });
prevLine = text = _.trunc(text, 40);
process.stdout.write(text + blankLine.slice(text.length) + '\r');
}
@@ -274,7 +298,7 @@ function logThrobber() {
* @returns {Array} Returns the new converted array.
*/
function optionToArray(name, string) {
return _.compact(_.invokeMap((optionToValue(name, string) || '').split(/, */), 'trim'));
return _.compact(_.invoke((optionToValue(name, string) || '').split(/, */), 'trim'));
}
/**
@@ -288,7 +312,7 @@ function optionToArray(name, string) {
function optionToValue(name, string) {
var result = string.match(RegExp('^' + name + '(?:=([\\s\\S]+))?$'));
if (result) {
result = _.get(result, 1);
result = _.result(result, 1);
result = result ? _.trim(result) : true;
}
if (result === 'false') {
@@ -360,8 +384,8 @@ function onJobStart(error, res, body) {
if (this.stopping) {
return;
}
var statusCode = _.get(res, 'statusCode'),
taskId = _.first(_.get(body, 'js tests'));
var statusCode = _.result(res, 'statusCode'),
taskId = _.first(_.result(body, 'js tests'));
if (error || !taskId || statusCode != 200) {
if (this.attempts < this.retries) {
@@ -402,19 +426,19 @@ function onJobStatus(error, res, body) {
if (!this.running || this.stopping) {
return;
}
var completed = _.get(body, 'completed', false),
data = _.first(_.get(body, 'js tests')),
var completed = _.result(body, 'completed', false),
data = _.first(_.result(body, 'js tests')),
elapsed = (_.now() - this.timestamp) / 1000,
jobId = _.get(data, 'job_id', null),
jobResult = _.get(data, 'result', null),
jobStatus = _.get(data, 'status', ''),
jobUrl = _.get(data, 'url', null),
jobId = _.result(data, 'job_id', null),
jobResult = _.result(data, 'result', null),
jobStatus = _.result(data, 'status', ''),
jobUrl = _.result(data, 'url', null),
expired = (elapsed >= queueTimeout && !_.includes(jobStatus, 'in progress')),
options = this.options,
platform = options.platforms[0];
if (_.isObject(jobResult)) {
var message = _.get(jobResult, 'message');
var message = _.result(jobResult, 'message');
} else {
if (typeof jobResult == 'string') {
message = jobResult;
@@ -434,9 +458,9 @@ function onJobStatus(error, res, body) {
this._pollerId = _.delay(_.bind(this.status, this), this.statusInterval * 1000);
return;
}
var description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + _.startCase(platform[0]),
var description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]),
errored = !jobResult || !jobResult.passed || reError.test(message) || reError.test(jobStatus),
failures = _.get(jobResult, 'failed'),
failures = _.result(jobResult, 'failed'),
label = options.name + ':',
tunnel = this.tunnel;
@@ -457,7 +481,7 @@ function onJobStatus(error, res, body) {
return;
}
else {
if (message === undefined) {
if (typeof message == 'undefined') {
message = 'Results are unavailable. ' + details;
}
console.error(label, description, chalk.red('failed') + ';', message);
@@ -536,7 +560,7 @@ util.inherits(Job, EventEmitter);
* @param {Object} Returns the job instance.
*/
Job.prototype.remove = function(callback) {
this.once('remove', _.iteratee(callback));
this.once('remove', _.callback(callback));
if (this.removing) {
return this;
}
@@ -561,7 +585,7 @@ Job.prototype.remove = function(callback) {
* @param {Object} Returns the job instance.
*/
Job.prototype.reset = function(callback) {
this.once('reset', _.iteratee(callback));
this.once('reset', _.callback(callback));
if (this.resetting) {
return this;
}
@@ -577,7 +601,7 @@ Job.prototype.reset = function(callback) {
* @param {Object} Returns the job instance.
*/
Job.prototype.restart = function(callback) {
this.once('restart', _.iteratee(callback));
this.once('restart', _.callback(callback));
if (this.restarting) {
return this;
}
@@ -585,7 +609,7 @@ Job.prototype.restart = function(callback) {
var options = this.options,
platform = options.platforms[0],
description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + _.startCase(platform[0]),
description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capitalizeWords(platform[0]),
label = options.name + ':';
logInline();
@@ -602,7 +626,7 @@ Job.prototype.restart = function(callback) {
* @param {Object} Returns the job instance.
*/
Job.prototype.start = function(callback) {
this.once('start', _.iteratee(callback));
this.once('start', _.callback(callback));
if (this.starting || this.running) {
return this;
}
@@ -623,7 +647,7 @@ Job.prototype.start = function(callback) {
* @param {Object} Returns the job instance.
*/
Job.prototype.status = function(callback) {
this.once('status', _.iteratee(callback));
this.once('status', _.callback(callback));
if (this.checking || this.removing || this.resetting || this.restarting || this.starting || this.stopping) {
return this;
}
@@ -645,7 +669,7 @@ Job.prototype.status = function(callback) {
* @param {Object} Returns the job instance.
*/
Job.prototype.stop = function(callback) {
this.once('stop', _.iteratee(callback));
this.once('stop', _.callback(callback));
if (this.stopping) {
return this;
}
@@ -683,14 +707,14 @@ function Tunnel(properties) {
var active = [],
queue = [];
var all = _.map(this.platforms, _.bind(function(platform) {
var all = _.map(this.platforms, function(platform) {
return new Job(_.merge({
'user': this.user,
'pass': this.pass,
'tunnel': this,
'options': { 'platforms': [platform] }
}, this.job));
}, this));
}, this);
var completed = 0,
restarted = [],
@@ -698,7 +722,7 @@ function Tunnel(properties) {
total = all.length,
tunnel = this;
_.invokeMap(all, 'on', 'complete', function() {
_.invoke(all, 'on', 'complete', function() {
_.pull(active, this);
if (success) {
success = !this.failed;
@@ -710,7 +734,7 @@ function Tunnel(properties) {
tunnel.dequeue();
});
_.invokeMap(all, 'on', 'restart', function() {
_.invoke(all, 'on', 'restart', function() {
if (!_.includes(restarted, this)) {
restarted.push(this);
}
@@ -744,7 +768,7 @@ util.inherits(Tunnel, EventEmitter);
* @param {Function} callback The function called once the tunnel is restarted.
*/
Tunnel.prototype.restart = function(callback) {
this.once('restart', _.iteratee(callback));
this.once('restart', _.callback(callback));
if (this.restarting) {
return this;
}
@@ -758,7 +782,7 @@ Tunnel.prototype.restart = function(callback) {
all = jobs.all;
var reset = _.after(all.length, _.bind(this.stop, this, onGenericRestart)),
stop = _.after(active.length, _.partial(_.invokeMap, all, 'reset', reset));
stop = _.after(active.length, _.partial(_.invoke, all, 'reset', reset));
if (_.isEmpty(active)) {
_.defer(stop);
@@ -766,7 +790,7 @@ Tunnel.prototype.restart = function(callback) {
if (_.isEmpty(all)) {
_.defer(reset);
}
_.invokeMap(active, 'stop', function() {
_.invoke(active, 'stop', function() {
_.pull(active, this);
stop();
});
@@ -786,7 +810,7 @@ Tunnel.prototype.restart = function(callback) {
* @param {Object} Returns the tunnel instance.
*/
Tunnel.prototype.start = function(callback) {
this.once('start', _.iteratee(callback));
this.once('start', _.callback(callback));
if (this.starting || this.running) {
return this;
}
@@ -810,16 +834,13 @@ Tunnel.prototype.start = function(callback) {
* @param {Object} Returns the tunnel instance.
*/
Tunnel.prototype.dequeue = function() {
var count = 0,
jobs = this.jobs,
var jobs = this.jobs,
active = jobs.active,
queue = jobs.queue,
throttled = this.throttled;
while (queue.length && (active.length < throttled)) {
var job = queue.shift();
active.push(job);
_.delay(_.bind(job.start, job), ++count * 1000);
active.push(queue.shift().start());
}
return this;
};
@@ -832,7 +853,7 @@ Tunnel.prototype.dequeue = function() {
* @param {Object} Returns the tunnel instance.
*/
Tunnel.prototype.stop = function(callback) {
this.once('stop', _.iteratee(callback));
this.once('stop', _.callback(callback));
if (this.stopping) {
return this;
}
@@ -857,7 +878,7 @@ Tunnel.prototype.stop = function(callback) {
if (_.isEmpty(active)) {
_.defer(stop);
}
_.invokeMap(active, 'stop', function() {
_.invoke(active, 'stop', function() {
_.pull(active, this);
stop();
});

File diff suppressed because it is too large Load Diff

28822
test/test.js

File diff suppressed because it is too large Load Diff

View File

@@ -23,91 +23,50 @@
<script src="../node_modules/jquery/dist/jquery.js"></script>
<script src="../node_modules/platform/platform.js"></script>
<script src="./asset/test-ui.js"></script>
<script src="../lodash.js"></script>
<script>
QUnit.config.asyncRetries = 10;
QUnit.config.hidepassed = true;
// Excuse tests we intentionally fail or those with problems.
QUnit.config.excused = {
'Arrays': {
'chunk': [
'defaults to empty array (chunk size 0)'
],
'difference': [
'can perform an OO-style difference'
],
'drop': [
'is an alias for rest'
'alias for rest'
],
'first': [
'returns an empty array when n <= 0 (0 case)',
'returns an empty array when n <= 0 (negative case)',
'can fetch the first n elements',
'returns the whole array if n > length'
],
'findIndex': [
'called with context'
],
'findLastIndex': [
'called with context'
],
'flatten': [
'supports empty arrays',
'can flatten nested arrays',
'works on an arguments object',
'can handle very deep arrays'
],
'indexOf': [
"sorted indexOf doesn't uses binary search",
'can pass an index to first',
'[1,2]',
'0'
],
'flatten': [
'Flattens empty arrays',
'can flatten nested arrays',
'can shallowly flatten nested arrays',
'works on an arguments object',
'can shallowly flatten arrays containing only other arrays'
],
'initial': [
'returns all but the last n elements',
'returns an empty array when n > length',
'works on an arguments object'
'initial can take an index',
'initial can take a large index',
'initial works on arguments object'
],
'intersection': [
'can perform an OO-style intersection'
],
'last': [
'returns an empty array when n <= 0 (0 case)',
'returns an empty array when n <= 0 (negative case)',
'can fetch the last n elements',
'returns the whole array if n > length'
'can pass an index to last',
'0'
],
'lastIndexOf': [
'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`',
'should treat non-number `fromIndex` values as `array.length`',
'[0,-1,-1]'
],
'object': [
'an array of pairs zipped together into an object',
'an object converted to pairs and back to an object'
],
'rest': [
'returns the whole array when index is 0',
'returns elements starting at the given index',
'works on an arguments object'
],
'sortedIndex': [
'2',
'3'
],
'tail': [
'is an alias for rest'
'working rest(0)',
'rest can take an index',
'works on arguments object'
],
'take': [
'is an alias for first'
],
'uniq': [
'uses the result of `iterator` for uniqueness comparisons (unsorted case)',
'`sorted` argument defaults to false when omitted',
'when `iterator` is a string, uses that key for comparisons (unsorted case)',
'uses the result of `iterator` for uniqueness comparisons (sorted case)',
'when `iterator` is a string, uses that key for comparisons (sorted case)',
'can use falsey pluck like iterator'
],
'union': [
'can perform an OO-style union'
'alias for first'
]
},
'Chaining': {
@@ -119,190 +78,69 @@
]
},
'Collections': {
'lookupIterator with contexts': true,
'Iterating objects with sketchy length properties': true,
'Resistant to collection length and properties changing while iterating': true,
'countBy': [
'{}',
'[{}]'
],
'each': [
'context object property accessed'
],
'every': [
'Can be called with object',
'Died on test #15',
'context works'
],
'filter': [
'given context',
'OO-filter'
],
'find': [
'called with context'
],
'findWhere': [
'checks properties given function'
],
'groupBy': [
'{}',
'[{}]'
],
'includes': [
"doesn't delegate to binary search"
],
'invoke': [
'handles null & undefined'
],
'map': [
'tripled numbers with context',
'OO-style doubled numbers'
],
'max': [
'can handle null/undefined',
'can perform a computation-based max',
'Maximum value of an empty object',
'Maximum value of an empty array',
'Maximum value of a non-numeric collection',
'Finds correct max in array starting with num and containing a NaN',
'Finds correct max in array starting with NaN',
'Respects iterator return value of -Infinity',
'String keys use property iterator',
'Iterator context',
'Lookup falsy iterator'
],
'min': [
'can handle null/undefined',
'can perform a computation-based min',
'Minimum value of an empty object',
'Minimum value of an empty array',
'Minimum value of a non-numeric collection',
'Finds correct min in array starting with NaN',
'Respects iterator return value of Infinity',
'String keys use property iterator',
'Iterator context',
'Lookup falsy iterator'
],
'partition': [
'can reference the array index',
'Died on test #8',
'partition takes a context argument'
],
'pluck': [
'[1]'
],
'reduce': [
'can reduce with a context object'
],
'reject': [
'Returns empty list given empty array'
],
'sample': [
'behaves correctly on negative n',
'Died on test #3'
],
'some': [
'Can be called with object',
'Died on test #17',
'context works'
],
'where': [
'checks properties given function'
],
'Can use various collection methods on NodeLists': [
'<span id="id2"></span>'
'Resistant to collection length and properties changing while iterating': [
'Died on test #50'
]
},
'Functions': {
'debounce asap': true,
'debounce asap cancel': true,
'debounce asap recursively': true,
'debounce after system time is set backwards': true,
'debounce re-entrant': true,
'throttle repeatedly with results': true,
'more throttle does not trigger leading call when leading is set to false': true,
'throttle does not trigger trailing call when trailing is set to false': true,
'before': true,
'bind': [
'Died on test #2'
],
'bindAll': [
'throws an error for bindAll with no functions named'
],
'debounce': [
'incr was debounced'
],
'iteratee': [
'"bbiz"',
'"foo"',
'1'
],
'memoize': [
'{"bar":"BAR","foo":"FOO"}',
'Died on test #8'
]
],
'throttle repeatedly with results': true,
'more throttle does not trigger leading call when leading is set to false': true,
'throttle does not trigger trailing call when trailing is set to false': true,
'debounce asap': true
},
'Objects': {
'#1929 Typed Array constructors are functions': true,
'allKeys': [
'is not fooled by sparse arrays; see issue #95',
'is not fooled by sparse arrays with additional properties',
'[]'
],
'allKeys': true,
'extendOwn': true,
'mapObject': true,
'matcher': true,
'matcher ': true,
'extend': [
'extending null results in null',
'extending undefined results in undefined'
],
'extendOwn': [
'extending non-objects results in returning the non-object value',
'extending undefined results in undefined'
],
'functions': [
'also looks up functions on the prototype'
'extend copies all properties from source'
],
'isEqual': [
'`0` is not equal to `-0`',
'Commutative equality is implemented for `0` and `-0`',
'`new Number(0)` and `-0` are not equal',
'Commutative equality is implemented for `new Number(0)` and `-0`',
'Invalid dates are not equal',
'false'
'Commutative equality is implemented for `new Number(0)` and `-0`'
],
'isFinite': [
'Numeric strings are numbers',
'Number instances can be finite'
],
'isSet': [
'Died on test #9'
],
'findKey': [
'called with context'
'isMatch': [
'inherited and own properties are checked on the test object',
'doesnt falsey match constructor on undefined/null'
],
'keys': [
'is not fooled by sparse arrays; see issue #95',
'[]'
],
'mapObject': [
'keep context',
'called with context',
'mapValue identity'
],
'omit': [
'can accept a predicate',
'function is given context'
],
'pick': [
'can accept a predicate and context',
'function is given context'
'matches': [
'inherited and own properties are checked on the test object',
'doesnt fasley match constructor on undefined/null'
]
},
'Utility': {
'_.escape & unescape': [
'` is escaped',
'` can be unescaped',
'can escape multiple occurances of `',
'multiple occurrences of ` can be unescaped'
],
'now': [
'Produces the correct time in milliseconds'
],
@@ -312,75 +150,19 @@
}
};
var mixinPrereqs = (function() {
var aliasToReal = {
'all': 'every',
'allKeys': 'keysIn',
'any': 'some',
'collect': 'map',
'compose': 'flowRight',
'contains': 'includes',
'detect': 'find',
'extendOwn': 'assign',
'findWhere': 'find',
'foldl': 'reduce',
'foldr': 'reduceRight',
'include': 'includes',
'indexBy': 'keyBy',
'inject': 'reduce',
'invoke': 'invokeMap',
'mapObject': 'mapValues',
'matcher': 'matches',
'methods': 'functions',
'object': 'zipObject',
'pairs': 'toPairs',
'pluck': 'map',
'restParam': 'restArgs',
'select': 'filter',
'unique': 'uniq',
'where': 'filter'
};
var keyMap = {
'rest': 'tail',
'restArgs': 'rest'
};
var lodash = _.noConflict();
return function(_) {
lodash(_)
.defaultsDeep({ 'templateSettings': lodash.templateSettings })
.mixin(lodash.pick(lodash, lodash.difference(lodash.functions(lodash), lodash.functions(_))))
.value();
lodash.forOwn(keyMap, function(realName, otherName) {
_[otherName] = lodash[realName];
_.prototype[otherName] = lodash.prototype[realName];
});
lodash.forOwn(aliasToReal, function(realName, alias) {
_[alias] = _[realName];
_.prototype[alias] = _.prototype[realName];
});
return _;
};
}());
// Only excuse in Sauce Labs.
// Only excuse in Sauce Labs (buggy Safari and timers).
if (!ui.isSauceLabs) {
delete QUnit.config.excused.Functions['throttle repeatedly with results'];
delete QUnit.config.excused.Functions['more throttle does not trigger leading call when leading is set to false'];
delete QUnit.config.excused.Functions['throttle does not trigger trailing call when trailing is set to false'];
delete QUnit.config.excused.Functions['debounce asap'];
delete QUnit.config.excused.Utility.now;
}
// Load prerequisite scripts.
document.write(ui.urlParams.loader == 'none'
? '<script src="' + ui.buildPath + '"><\/script>'
: '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
);
</script>
<script>
if (ui.urlParams.loader == 'none') {
mixinPrereqs(_);
document.write([
// Load test scripts.
document.write(ui.urlParams.loader != 'none'
? '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
: ([
'<script src="' + ui.buildPath + '"><\/script>',
'<script src="../vendor/underscore/test/collections.js"><\/script>',
'<script src="../vendor/underscore/test/arrays.js"><\/script>',
'<script src="../vendor/underscore/test/functions.js"><\/script>',
@@ -388,8 +170,8 @@
'<script src="../vendor/underscore/test/cross-document.js"><\/script>',
'<script src="../vendor/underscore/test/utility.js"><\/script>',
'<script src="../vendor/underscore/test/chaining.js"><\/script>'
].join('\n'));
}
].join('\n'))
);
</script>
<script>
(function() {
@@ -399,13 +181,6 @@
if (!window.require) {
return;
}
// Wrap to work around tests assuming Node `require` use.
require = (function(func) {
return function() {
return arguments[0] === '..' ? window._ : func.apply(null, arguments);
};
}(require));
var reBasename = /[\w.-]+$/,
basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''),
modulePath = ui.buildPath.replace(/\.js$/, ''),
@@ -444,12 +219,11 @@
}
QUnit.config.autostart = false;
QUnit.config.excused.Functions.iteratee = true;
QUnit.config.excused.Utility.noConflict = true;
QUnit.config.excused.Utility['noConflict (node vm)'] = true;
require(getConfig(), [moduleId], function(lodash) {
_ = mixinPrereqs(lodash);
if (ui.isModularize) {
window._ = lodash;
}
require(getConfig(), [
'test/collections',
'test/arrays',
@@ -458,7 +232,9 @@
'test/cross-document',
'test/utility',
'test/chaining'
], QUnit.start);
], function() {
QUnit.start();
});
});
}());
</script>

View File

@@ -1,4 +1,4 @@
Copyright (c) 2010-2016 Jeremy Ashkenas, DocumentCloud
Copyright (c) 2010-2015 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

View File

@@ -1,6 +1,6 @@
// Backbone.js 1.3.3
// Backbone.js 1.2.1
// (c) 2010-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2010-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
@@ -9,8 +9,8 @@
// Establish the root object, `window` (`self`) in the browser, or `global` on the server.
// We use `self` instead of `window` for `WebWorker` support.
var root = (typeof self == 'object' && self.self === self && self) ||
(typeof global == 'object' && global.global === global && global);
var root = (typeof self == 'object' && self.self == self && self) ||
(typeof global == 'object' && global.global == global && global);
// Set up Backbone appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
@@ -23,7 +23,7 @@
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $;
try { $ = require('jquery'); } catch (e) {}
try { $ = require('jquery'); } catch(e) {}
factory(root, exports, _, $);
// Finally, as a browser global.
@@ -31,7 +31,7 @@
root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
}
})(function(root, Backbone, _, $) {
}(function(root, Backbone, _, $) {
// Initial Setup
// -------------
@@ -41,10 +41,10 @@
var previousBackbone = root.Backbone;
// Create a local reference to a common array method we'll want to use later.
var slice = Array.prototype.slice;
var slice = [].slice;
// Current version of the library. Keep in sync with `package.json`.
Backbone.VERSION = '1.3.3';
Backbone.VERSION = '1.2.1';
// For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
// the `$` variable.
@@ -68,13 +68,8 @@
// form param named `model`.
Backbone.emulateJSON = false;
// Proxy Backbone class methods to Underscore functions, wrapping the model's
// `attributes` object or collection's `models` array behind the scenes.
//
// collection.filter(function(model) { return model.get('age') > 10 });
// collection.each(this.addView);
//
// `Function#apply` can be slow so we use the method's arg count, if we know it.
// Proxy Underscore methods to a Backbone class' prototype using a
// particular attribute as the data argument
var addMethod = function(length, method, attribute) {
switch (length) {
case 1: return function() {
@@ -84,10 +79,10 @@
return _[method](this[attribute], value);
};
case 3: return function(iteratee, context) {
return _[method](this[attribute], cb(iteratee, this), context);
return _[method](this[attribute], iteratee, context);
};
case 4: return function(iteratee, defaultVal, context) {
return _[method](this[attribute], cb(iteratee, this), defaultVal, context);
return _[method](this[attribute], iteratee, defaultVal, context);
};
default: return function() {
var args = slice.call(arguments);
@@ -102,26 +97,12 @@
});
};
// Support `collection.sortBy('attr')` and `collection.findWhere({id: 1})`.
var cb = function(iteratee, instance) {
if (_.isFunction(iteratee)) return iteratee;
if (_.isObject(iteratee) && !instance._isModel(iteratee)) return modelMatcher(iteratee);
if (_.isString(iteratee)) return function(model) { return model.get(iteratee); };
return iteratee;
};
var modelMatcher = function(attrs) {
var matcher = _.matches(attrs);
return function(model) {
return matcher(model.attributes);
};
};
// Backbone.Events
// ---------------
// A module that can be mixed in to *any object* in order to provide it with
// a custom event channel. You may bind a callback to an event with `on` or
// remove with `off`; `trigger`-ing an event fires all callbacks in
// custom events. You may bind with `on` or remove with `off` callback
// functions to an event; `trigger`-ing an event fires all callbacks in
// succession.
//
// var object = {};
@@ -136,25 +117,26 @@
// Iterates over the standard `event, callback` (as well as the fancy multiple
// space-separated events `"change blur", callback` and jQuery-style event
// maps `{event: callback}`).
var eventsApi = function(iteratee, events, name, callback, opts) {
// maps `{event: callback}`), reducing them by manipulating `memo`.
// Passes a normalized single event name and callback, as well as any
// optional `opts`.
var eventsApi = function(iteratee, memo, name, callback, opts) {
var i = 0, names;
if (name && typeof name === 'object') {
// Handle event maps.
if (callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
for (names = _.keys(name); i < names.length ; i++) {
events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
memo = iteratee(memo, names[i], name[names[i]], opts);
}
} else if (name && eventSplitter.test(name)) {
// Handle space-separated event names by delegating them individually.
// Handle space separated event names.
for (names = name.split(eventSplitter); i < names.length; i++) {
events = iteratee(events, names[i], callback, opts);
memo = iteratee(memo, names[i], callback, opts);
}
} else {
// Finally, standard events.
events = iteratee(events, name, callback, opts);
memo = iteratee(memo, name, callback, opts);
}
return events;
return memo;
};
// Bind an event to a `callback` function. Passing `"all"` will bind
@@ -163,12 +145,13 @@
return internalOn(this, name, callback, context);
};
// Guard the `listening` argument from the public API.
// An internal use `on` function, used to guard the `listening` argument from
// the public API.
var internalOn = function(obj, name, callback, context, listening) {
obj._events = eventsApi(onApi, obj._events || {}, name, callback, {
context: context,
ctx: obj,
listening: listening
context: context,
ctx: obj,
listening: listening
});
if (listening) {
@@ -180,9 +163,8 @@
};
// Inversion-of-control versions of `on`. Tell *this* object to listen to
// an event in another object... keeping track of what it's listening to
// for easier unbinding later.
Events.listenTo = function(obj, name, callback) {
// an event in another object... keeping track of what it's listening to.
Events.listenTo = function(obj, name, callback) {
if (!obj) return this;
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
var listeningTo = this._listeningTo || (this._listeningTo = {});
@@ -207,7 +189,7 @@
var context = options.context, ctx = options.ctx, listening = options.listening;
if (listening) listening.count++;
handlers.push({callback: callback, context: context, ctx: context || ctx, listening: listening});
handlers.push({ callback: callback, context: context, ctx: context || ctx, listening: listening });
}
return events;
};
@@ -216,18 +198,18 @@
// callbacks with that function. If `callback` is null, removes all
// callbacks for the event. If `name` is null, removes all bound
// callbacks for all events.
Events.off = function(name, callback, context) {
Events.off = function(name, callback, context) {
if (!this._events) return this;
this._events = eventsApi(offApi, this._events, name, callback, {
context: context,
listeners: this._listeners
context: context,
listeners: this._listeners
});
return this;
};
// Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to.
Events.stopListening = function(obj, name, callback) {
Events.stopListening = function(obj, name, callback) {
var listeningTo = this._listeningTo;
if (!listeningTo) return this;
@@ -242,12 +224,14 @@
listening.obj.off(name, callback, this);
}
if (_.isEmpty(listeningTo)) this._listeningTo = void 0;
return this;
};
// The reducing API that removes a callback from the `events` object.
var offApi = function(events, name, callback, options) {
// No events to consider.
if (!events) return;
var i = 0, listening;
@@ -298,22 +282,21 @@
delete events[name];
}
}
return events;
if (_.size(events)) return events;
};
// Bind an event to only be triggered a single time. After the first time
// the callback is invoked, its listener will be removed. If multiple events
// are passed in using the space-separated syntax, the handler will fire
// once for each event, not once for a combination of all events.
Events.once = function(name, callback, context) {
// the callback is invoked, it will be removed. When multiple events are
// passed in using the space-separated syntax, the event will fire once for every
// event you passed in, not once for a combination of all events
Events.once = function(name, callback, context) {
// Map the event into a `{event: once}` object.
var events = eventsApi(onceMap, {}, name, callback, _.bind(this.off, this));
if (typeof name === 'string' && context == null) callback = void 0;
return this.on(events, callback, context);
return this.on(events, void 0, context);
};
// Inversion-of-control versions of `once`.
Events.listenToOnce = function(obj, name, callback) {
Events.listenToOnce = function(obj, name, callback) {
// Map the event into a `{event: once}` object.
var events = eventsApi(onceMap, {}, name, callback, _.bind(this.stopListening, this, obj));
return this.listenTo(obj, events);
@@ -336,7 +319,7 @@
// passed the same arguments as `trigger` is, apart from the event name
// (unless you're listening on `"all"`, which will cause your callback to
// receive the true name of the event as the first argument).
Events.trigger = function(name) {
Events.trigger = function(name) {
if (!this._events) return this;
var length = Math.max(0, arguments.length - 1);
@@ -348,7 +331,7 @@
};
// Handles triggering the appropriate event callbacks.
var triggerApi = function(objEvents, name, callback, args) {
var triggerApi = function(objEvents, name, cb, args) {
if (objEvents) {
var events = objEvents[name];
var allEvents = objEvents.all;
@@ -394,13 +377,11 @@
var Model = Backbone.Model = function(attributes, options) {
var attrs = attributes || {};
options || (options = {});
this.preinitialize.apply(this, arguments);
this.cid = _.uniqueId(this.cidPrefix);
this.attributes = {};
if (options.collection) this.collection = options.collection;
if (options.parse) attrs = this.parse(attrs, options) || {};
var defaults = _.result(this, 'defaults');
attrs = _.defaults(_.extend({}, defaults, attrs), defaults);
attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
this.set(attrs, options);
this.changed = {};
this.initialize.apply(this, arguments);
@@ -423,10 +404,6 @@
// You may want to override this if you're experiencing name clashes with model ids.
cidPrefix: 'c',
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Model.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){},
@@ -499,6 +476,9 @@
var changed = this.changed;
var prev = this._previousAttributes;
// Check for changes of `id`.
if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
// For each `set` attribute, update or delete the current value.
for (var attr in attrs) {
val = attrs[attr];
@@ -511,9 +491,6 @@
unset ? delete current[attr] : current[attr] = val;
}
// Update the `id`.
if (this.idAttribute in attrs) this.id = this.get(this.idAttribute);
// Trigger all relevant attribute changes.
if (!silent) {
if (changes.length) this._pending = options;
@@ -567,14 +544,12 @@
if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
var old = this._changing ? this._previousAttributes : this.attributes;
var changed = {};
var hasChanged;
for (var attr in diff) {
var val = diff[attr];
if (_.isEqual(old[attr], val)) continue;
changed[attr] = val;
hasChanged = true;
}
return hasChanged ? changed : false;
return _.size(changed) ? changed : false;
},
// Get the previous value of an attribute, recorded at the time the last
@@ -627,8 +602,8 @@
// the model will be valid when the attributes, if any, are set.
if (attrs && !wait) {
if (!this.set(attrs, options)) return false;
} else if (!this._validate(attrs, options)) {
return false;
} else {
if (!this._validate(attrs, options)) return false;
}
// After a successful server-side save, the client is (optionally)
@@ -722,7 +697,7 @@
// Check if the model is currently in a valid state.
isValid: function(options) {
return this._validate({}, _.extend({}, options, {validate: true}));
return this._validate({}, _.defaults({validate: true}, options));
},
// Run validation against the next complete set of model attributes,
@@ -738,10 +713,9 @@
});
// Underscore methods that we want to implement on the Model, mapped to the
// number of arguments they take.
var modelMethods = {keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
omit: 0, chain: 1, isEmpty: 1};
// Underscore methods that we want to implement on the Model.
var modelMethods = { keys: 1, values: 1, pairs: 1, invert: 1, pick: 0,
omit: 0, chain: 1, isEmpty: 1 };
// Mix in each Underscore method as a proxy to `Model#attributes`.
addUnderscoreMethods(Model, modelMethods, 'attributes');
@@ -761,7 +735,6 @@
// its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function(models, options) {
options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset();
@@ -773,17 +746,6 @@
var setOptions = {add: true, remove: true, merge: true};
var addOptions = {add: true, remove: false};
// Splices `insert` into `array` at index `at`.
var splice = function(array, insert, at) {
at = Math.min(Math.max(at, 0), array.length);
var tail = Array(array.length - at);
var length = insert.length;
var i;
for (i = 0; i < tail.length; i++) tail[i] = array[i + at];
for (i = 0; i < length; i++) array[i + at] = insert[i];
for (i = 0; i < tail.length; i++) array[i + length + at] = tail[i];
};
// Define the Collection's inheritable methods.
_.extend(Collection.prototype, Events, {
@@ -791,11 +753,6 @@
// This should be overridden in most cases.
model: Model,
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Collection.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){},
@@ -811,9 +768,7 @@
return Backbone.sync.apply(this, arguments);
},
// Add a model, or list of models to the set. `models` may be Backbone
// Models or raw JavaScript objects to be converted to Models, or any
// combination of the two.
// Add a model, or list of models to the set.
add: function(models, options) {
return this.set(models, _.extend({merge: false}, options, addOptions));
},
@@ -822,12 +777,9 @@
remove: function(models, options) {
options = _.extend({}, options);
var singular = !_.isArray(models);
models = singular ? [models] : models.slice();
models = singular ? [models] : _.clone(models);
var removed = this._removeModels(models, options);
if (!options.silent && removed.length) {
options.changes = {added: [], merged: [], removed: removed};
this.trigger('update', this, options);
}
if (!options.silent && removed) this.trigger('update', this, options);
return singular ? removed[0] : removed;
},
@@ -836,114 +788,97 @@
// already exist in the collection, as necessary. Similar to **Model#set**,
// the core operation for updating the data contained by the collection.
set: function(models, options) {
if (models == null) return;
options = _.extend({}, setOptions, options);
if (options.parse && !this._isModel(models)) {
models = this.parse(models, options) || [];
}
options = _.defaults({}, options, setOptions);
if (options.parse && !this._isModel(models)) models = this.parse(models, options);
var singular = !_.isArray(models);
models = singular ? [models] : models.slice();
models = singular ? (models ? [models] : []) : models.slice();
var id, model, attrs, existing, sort;
var at = options.at;
if (at != null) at = +at;
if (at > this.length) at = this.length;
if (at < 0) at += this.length + 1;
var set = [];
var toAdd = [];
var toMerge = [];
var toRemove = [];
var modelMap = {};
var add = options.add;
var merge = options.merge;
var remove = options.remove;
var sort = false;
var sortable = this.comparator && at == null && options.sort !== false;
var sortable = this.comparator && (at == null) && options.sort !== false;
var sortAttr = _.isString(this.comparator) ? this.comparator : null;
var toAdd = [], toRemove = [], modelMap = {};
var add = options.add, merge = options.merge, remove = options.remove;
var order = !sortable && add && remove ? [] : false;
var orderChanged = false;
// Turn bare objects into model references, and prevent invalid models
// from being added.
var model, i;
for (i = 0; i < models.length; i++) {
model = models[i];
for (var i = 0; i < models.length; i++) {
attrs = models[i];
// If a duplicate is found, prevent it from being added and
// optionally merge it into the existing model.
var existing = this.get(model);
if (existing) {
if (merge && model !== existing) {
var attrs = this._isModel(model) ? model.attributes : model;
if (existing = this.get(attrs)) {
if (remove) modelMap[existing.cid] = true;
if (merge && attrs !== existing) {
attrs = this._isModel(attrs) ? attrs.attributes : attrs;
if (options.parse) attrs = existing.parse(attrs, options);
existing.set(attrs, options);
toMerge.push(existing);
if (sortable && !sort) sort = existing.hasChanged(sortAttr);
}
if (!modelMap[existing.cid]) {
modelMap[existing.cid] = true;
set.push(existing);
if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
}
models[i] = existing;
// If this is a new, valid model, push it to the `toAdd` list.
} else if (add) {
model = models[i] = this._prepareModel(model, options);
if (model) {
toAdd.push(model);
this._addReference(model, options);
modelMap[model.cid] = true;
set.push(model);
}
model = models[i] = this._prepareModel(attrs, options);
if (!model) continue;
toAdd.push(model);
this._addReference(model, options);
}
// Do not add multiple models with the same `id`.
model = existing || model;
if (!model) continue;
id = this.modelId(model.attributes);
if (order && (model.isNew() || !modelMap[id])) {
order.push(model);
// Check to see if this is actually a new model at this index.
orderChanged = orderChanged || !this.models[i] || model.cid !== this.models[i].cid;
}
modelMap[id] = true;
}
// Remove stale models.
// Remove nonexistent models if appropriate.
if (remove) {
for (i = 0; i < this.length; i++) {
model = this.models[i];
if (!modelMap[model.cid]) toRemove.push(model);
for (var i = 0; i < this.length; i++) {
if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
}
if (toRemove.length) this._removeModels(toRemove, options);
}
// See if sorting is needed, update `length` and splice in new models.
var orderChanged = false;
var replace = !sortable && add && remove;
if (set.length && replace) {
orderChanged = this.length !== set.length || _.some(this.models, function(m, index) {
return m !== set[index];
});
this.models.length = 0;
splice(this.models, set, 0);
this.length = this.models.length;
} else if (toAdd.length) {
if (toAdd.length || orderChanged) {
if (sortable) sort = true;
splice(this.models, toAdd, at == null ? this.length : at);
this.length = this.models.length;
this.length += toAdd.length;
if (at != null) {
for (var i = 0; i < toAdd.length; i++) {
this.models.splice(at + i, 0, toAdd[i]);
}
} else {
if (order) this.models.length = 0;
var orderedModels = order || toAdd;
for (var i = 0; i < orderedModels.length; i++) {
this.models.push(orderedModels[i]);
}
}
}
// Silently sort the collection if appropriate.
if (sort) this.sort({silent: true});
// Unless silenced, it's time to fire all appropriate add/sort/update events.
// Unless silenced, it's time to fire all appropriate add/sort events.
if (!options.silent) {
for (i = 0; i < toAdd.length; i++) {
if (at != null) options.index = at + i;
model = toAdd[i];
model.trigger('add', model, this, options);
var addOpts = at != null ? _.clone(options) : options;
for (var i = 0; i < toAdd.length; i++) {
if (at != null) addOpts.index = at + i;
(model = toAdd[i]).trigger('add', model, this, addOpts);
}
if (sort || orderChanged) this.trigger('sort', this, options);
if (toAdd.length || toRemove.length || toMerge.length) {
options.changes = {
added: toAdd,
removed: toRemove,
merged: toMerge
};
this.trigger('update', this, options);
}
if (toAdd.length || toRemove.length) this.trigger('update', this, options);
}
// Return the added (or merged) model (or models).
@@ -993,18 +928,11 @@
return slice.apply(this.models, arguments);
},
// Get a model from the set by id, cid, model object with id or cid
// properties, or an attributes object that is transformed through modelId.
// Get a model from the set by id.
get: function(obj) {
if (obj == null) return void 0;
return this._byId[obj] ||
this._byId[this.modelId(obj.attributes || obj)] ||
obj.cid && this._byId[obj.cid];
},
// Returns `true` if the model is in the collection.
has: function(obj) {
return this.get(obj) != null;
var id = this.modelId(this._isModel(obj) ? obj.attributes : obj);
return this._byId[obj] || this._byId[id] || this._byId[obj.cid];
},
// Get the model at the given index.
@@ -1016,7 +944,10 @@
// Return models with matching attributes. Useful for simple cases of
// `filter`.
where: function(attrs, first) {
return this[first ? 'find' : 'filter'](attrs);
var matches = _.matches(attrs);
return this[first ? 'find' : 'filter'](function(model) {
return matches(model.attributes);
});
},
// Return the first model with matching attributes. Useful for simple cases
@@ -1029,26 +960,23 @@
// normal circumstances, as the set will maintain sort order as each item
// is added.
sort: function(options) {
var comparator = this.comparator;
if (!comparator) throw new Error('Cannot sort a set without a comparator');
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
options || (options = {});
var length = comparator.length;
if (_.isFunction(comparator)) comparator = _.bind(comparator, this);
// Run sort based on type of `comparator`.
if (length === 1 || _.isString(comparator)) {
this.models = this.sortBy(comparator);
if (_.isString(this.comparator) || this.comparator.length === 1) {
this.models = this.sortBy(this.comparator, this);
} else {
this.models.sort(comparator);
this.models.sort(_.bind(this.comparator, this));
}
if (!options.silent) this.trigger('sort', this, options);
return this;
},
// Pluck an attribute from each model in the collection.
pluck: function(attr) {
return this.map(attr + '');
return _.invoke(this.models, 'get', attr);
},
// Fetch the default set of models for this collection, resetting the
@@ -1079,9 +1007,9 @@
if (!wait) this.add(model, options);
var collection = this;
var success = options.success;
options.success = function(m, resp, callbackOpts) {
if (wait) collection.add(m, callbackOpts);
if (success) success.call(callbackOpts.context, m, resp, callbackOpts);
options.success = function(model, resp, callbackOpts) {
if (wait) collection.add(model, callbackOpts);
if (success) success.call(callbackOpts.context, model, resp, callbackOpts);
};
model.save(null, options);
return model;
@@ -1102,7 +1030,7 @@
},
// Define how to uniquely identify models in the collection.
modelId: function(attrs) {
modelId: function (attrs) {
return attrs[this.model.prototype.idAttribute || 'id'];
},
@@ -1130,6 +1058,7 @@
},
// Internal method called by both remove and set.
// Returns removed models, or false if nothing is removed.
_removeModels: function(models, options) {
var removed = [];
for (var i = 0; i < models.length; i++) {
@@ -1140,12 +1069,6 @@
this.models.splice(index, 1);
this.length--;
// Remove references before triggering 'remove' event to prevent an
// infinite loop. #3693
delete this._byId[model.cid];
var id = this.modelId(model.attributes);
if (id != null) delete this._byId[id];
if (!options.silent) {
options.index = index;
model.trigger('remove', model, this, options);
@@ -1154,12 +1077,12 @@
removed.push(model);
this._removeReference(model, options);
}
return removed;
return removed.length ? removed : false;
},
// Method for checking whether an object should be considered a model for
// the purposes of adding to the collection.
_isModel: function(model) {
_isModel: function (model) {
return model instanceof Model;
},
@@ -1185,16 +1108,14 @@
// events simply proxy through. "add" and "remove" events that originate
// in other collections are ignored.
_onModelEvent: function(event, model, collection, options) {
if (model) {
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (event === 'change') {
var prevId = this.modelId(model.previousAttributes());
var id = this.modelId(model.attributes);
if (prevId !== id) {
if (prevId != null) delete this._byId[prevId];
if (id != null) this._byId[id] = model;
}
if ((event === 'add' || event === 'remove') && collection !== this) return;
if (event === 'destroy') this.remove(model, options);
if (event === 'change') {
var prevId = this.modelId(model.previousAttributes());
var id = this.modelId(model.attributes);
if (prevId !== id) {
if (prevId != null) delete this._byId[prevId];
if (id != null) this._byId[id] = model;
}
}
this.trigger.apply(this, arguments);
@@ -1205,18 +1126,31 @@
// Underscore methods that we want to implement on the Collection.
// 90% of the core usefulness of Backbone Collections is actually implemented
// right here:
var collectionMethods = {forEach: 3, each: 3, map: 3, collect: 3, reduce: 0,
foldl: 0, inject: 0, reduceRight: 0, foldr: 0, find: 3, detect: 3, filter: 3,
select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 3, includes: 3,
contains: 3, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
var collectionMethods = { forEach: 3, each: 3, map: 3, collect: 3, reduce: 4,
foldl: 4, inject: 4, reduceRight: 4, foldr: 4, find: 3, detect: 3, filter: 3,
select: 3, reject: 3, every: 3, all: 3, some: 3, any: 3, include: 2,
contains: 2, invoke: 0, max: 3, min: 3, toArray: 1, size: 1, first: 3,
head: 3, take: 3, initial: 3, rest: 3, tail: 3, drop: 3, last: 3,
without: 0, difference: 0, indexOf: 3, shuffle: 1, lastIndexOf: 3,
isEmpty: 1, chain: 1, sample: 3, partition: 3, groupBy: 3, countBy: 3,
sortBy: 3, indexBy: 3, findIndex: 3, findLastIndex: 3};
isEmpty: 1, chain: 1, sample: 3, partition: 3 };
// Mix in each Underscore method as a proxy to `Collection#models`.
addUnderscoreMethods(Collection, collectionMethods, 'models');
// Underscore methods that take a property name as an argument.
var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
// Use attributes instead of properties.
_.each(attributeMethods, function(method) {
if (!_[method]) return;
Collection.prototype[method] = function(value, context) {
var iterator = _.isFunction(value) ? value : function(model) {
return model.get(value);
};
return _[method](this.models, iterator, context);
};
});
// Backbone.View
// -------------
@@ -1232,7 +1166,6 @@
// if an existing element is not provided...
var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view');
this.preinitialize.apply(this, arguments);
_.extend(this, _.pick(options, viewOptions));
this._ensureElement();
this.initialize.apply(this, arguments);
@@ -1241,7 +1174,7 @@
// Cached regex to split keys for `delegate`.
var delegateEventSplitter = /^(\S+)\s*(.*)$/;
// List of view options to be set as properties.
// List of view options to be merged as properties.
var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
// Set up all inheritable **Backbone.View** properties and methods.
@@ -1256,10 +1189,6 @@
return this.$el.find(selector);
},
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the View
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){},
@@ -1467,9 +1396,9 @@
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
'read': 'GET'
};
// Set the default implementation of `Backbone.ajax` to proxy through to `$`.
@@ -1485,7 +1414,6 @@
// matched. Creating a new one sets its `routes` hash, if not set statically.
var Router = Backbone.Router = function(options) {
options || (options = {});
this.preinitialize.apply(this, arguments);
if (options.routes) this.routes = options.routes;
this._bindRoutes();
this.initialize.apply(this, arguments);
@@ -1501,10 +1429,6 @@
// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Router.prototype, Events, {
// preinitialize is an empty function by default. You can override it with a function
// or object. preinitialize will run before any instantiation logic is run in the Router.
preinitialize: function(){},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){},
@@ -1594,7 +1518,7 @@
// falls back to polling.
var History = Backbone.History = function() {
this.handlers = [];
this.checkUrl = _.bind(this.checkUrl, this);
_.bindAll(this, 'checkUrl');
// Ensure that `History` can be used outside of the browser.
if (typeof window !== 'undefined') {
@@ -1631,8 +1555,8 @@
// Does the pathname match the root?
matchRoot: function() {
var path = this.decodeFragment(this.location.pathname);
var rootPath = path.slice(0, this.root.length - 1) + '/';
return rootPath === this.root;
var root = path.slice(0, this.root.length - 1) + '/';
return root === this.root;
},
// Unicode characters in `location.pathname` are percent encoded so they're
@@ -1687,7 +1611,7 @@
this.options = _.extend({root: '/'}, this.options, options);
this.root = this.options.root;
this._wantsHashChange = this.options.hashChange !== false;
this._hasHashChange = 'onhashchange' in window && (document.documentMode === void 0 || document.documentMode > 7);
this._hasHashChange = 'onhashchange' in window;
this._useHashChange = this._wantsHashChange && this._hasHashChange;
this._wantsPushState = !!this.options.pushState;
this._hasPushState = !!(this.history && this.history.pushState);
@@ -1704,8 +1628,8 @@
// If we've started off with a route from a `pushState`-enabled
// browser, but we're currently in a browser that doesn't support it...
if (!this._hasPushState && !this.atRoot()) {
var rootPath = this.root.slice(0, -1) || '/';
this.location.replace(rootPath + '#' + this.getPath());
var root = this.root.slice(0, -1) || '/';
this.location.replace(root + '#' + this.getPath());
// Return immediately as browser will do redirect to new url
return true;
@@ -1734,7 +1658,7 @@
}
// Add a cross-platform `addEventListener` shim for older browsers.
var addEventListener = window.addEventListener || function(eventName, listener) {
var addEventListener = window.addEventListener || function (eventName, listener) {
return attachEvent('on' + eventName, listener);
};
@@ -1755,7 +1679,7 @@
// but possibly useful for unit testing Routers.
stop: function() {
// Add a cross-platform `removeEventListener` shim for older browsers.
var removeEventListener = window.removeEventListener || function(eventName, listener) {
var removeEventListener = window.removeEventListener || function (eventName, listener) {
return detachEvent('on' + eventName, listener);
};
@@ -1806,7 +1730,7 @@
// If the root doesn't match, no routes can match either.
if (!this.matchRoot()) return false;
fragment = this.fragment = this.getFragment(fragment);
return _.some(this.handlers, function(handler) {
return _.any(this.handlers, function(handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
@@ -1829,20 +1753,17 @@
fragment = this.getFragment(fragment || '');
// Don't include a trailing slash on the root.
var rootPath = this.root;
var root = this.root;
if (fragment === '' || fragment.charAt(0) === '?') {
rootPath = rootPath.slice(0, -1) || '/';
root = root.slice(0, -1) || '/';
}
var url = rootPath + fragment;
var url = root + fragment;
// Strip the fragment of the query and hash for matching.
fragment = fragment.replace(pathStripper, '');
// Strip the hash and decode for matching.
fragment = this.decodeFragment(fragment.replace(pathStripper, ''));
// Decode for matching.
var decodedFragment = this.decodeFragment(fragment);
if (this.fragment === decodedFragment) return;
this.fragment = decodedFragment;
if (this.fragment === fragment) return;
this.fragment = fragment;
// If pushState is available, we use it to set the fragment as a real URL.
if (this._usePushState) {
@@ -1852,7 +1773,7 @@
// fragment to store history.
} else if (this._wantsHashChange) {
this._updateHash(this.location, fragment, options.replace);
if (this.iframe && fragment !== this.getHash(this.iframe.contentWindow)) {
if (this.iframe && (fragment !== this.getHash(this.iframe.contentWindow))) {
var iWindow = this.iframe.contentWindow;
// Opening and closing the iframe tricks IE7 and earlier to push a
@@ -1914,9 +1835,14 @@
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function and add the prototype properties.
child.prototype = _.create(parent.prototype, protoProps);
child.prototype.constructor = child;
// `parent` constructor function.
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Set a convenience property in case the parent's prototype is needed
// later.
@@ -1943,4 +1869,5 @@
};
return Backbone;
});
}));

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,42 @@
(function(QUnit) {
(function() {
QUnit.module('Backbone.Events');
module("Backbone.Events");
QUnit.test('on and trigger', function(assert) {
assert.expect(2);
var obj = {counter: 0};
_.extend(obj, Backbone.Events);
test("on and trigger", 2, function() {
var obj = { counter: 0 };
_.extend(obj,Backbone.Events);
obj.on('event', function() { obj.counter += 1; });
obj.trigger('event');
assert.equal(obj.counter, 1, 'counter should be incremented.');
equal(obj.counter,1,'counter should be incremented.');
obj.trigger('event');
obj.trigger('event');
obj.trigger('event');
obj.trigger('event');
assert.equal(obj.counter, 5, 'counter should be incremented five times.');
equal(obj.counter, 5, 'counter should be incremented five times.');
});
QUnit.test('binding and triggering multiple events', function(assert) {
assert.expect(4);
var obj = {counter: 0};
test("binding and triggering multiple events", 4, function() {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
obj.on('a b c', function() { obj.counter += 1; });
obj.trigger('a');
assert.equal(obj.counter, 1);
equal(obj.counter, 1);
obj.trigger('a b');
assert.equal(obj.counter, 3);
equal(obj.counter, 3);
obj.trigger('c');
assert.equal(obj.counter, 4);
equal(obj.counter, 4);
obj.off('a c');
obj.trigger('a b c');
assert.equal(obj.counter, 5);
equal(obj.counter, 5);
});
QUnit.test('binding and triggering with event maps', function(assert) {
var obj = {counter: 0};
test("binding and triggering with event maps", function() {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
var increment = function() {
@@ -52,85 +50,54 @@
}, obj);
obj.trigger('a');
assert.equal(obj.counter, 1);
equal(obj.counter, 1);
obj.trigger('a b');
assert.equal(obj.counter, 3);
equal(obj.counter, 3);
obj.trigger('c');
assert.equal(obj.counter, 4);
equal(obj.counter, 4);
obj.off({
a: increment,
c: increment
}, obj);
obj.trigger('a b c');
assert.equal(obj.counter, 5);
equal(obj.counter, 5);
});
QUnit.test('binding and triggering multiple event names with event maps', function(assert) {
var obj = {counter: 0};
_.extend(obj, Backbone.Events);
var increment = function() {
this.counter += 1;
};
obj.on({
'a b c': increment
});
obj.trigger('a');
assert.equal(obj.counter, 1);
obj.trigger('a b');
assert.equal(obj.counter, 3);
obj.trigger('c');
assert.equal(obj.counter, 4);
obj.off({
'a c': increment
});
obj.trigger('a b c');
assert.equal(obj.counter, 5);
});
QUnit.test('binding and trigger with event maps context', function(assert) {
assert.expect(2);
var obj = {counter: 0};
test("binding and trigger with event maps context", 2, function() {
var obj = { counter: 0 };
var context = {};
_.extend(obj, Backbone.Events);
obj.on({
a: function() {
assert.strictEqual(this, context, 'defaults `context` to `callback` param');
}
a: function() {
strictEqual(this, context, 'defaults `context` to `callback` param');
}
}, context).trigger('a');
obj.off().on({
a: function() {
assert.strictEqual(this, context, 'will not override explicit `context` param');
}
a: function() {
strictEqual(this, context, 'will not override explicit `context` param');
}
}, this, context).trigger('a');
});
QUnit.test('listenTo and stopListening', function(assert) {
assert.expect(1);
test("listenTo and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, 'all', function(){ assert.ok(true); });
a.listenTo(b, 'all', function(){ ok(true); });
b.trigger('anything');
a.listenTo(b, 'all', function(){ assert.ok(false); });
a.listenTo(b, 'all', function(){ ok(false); });
a.stopListening();
b.trigger('anything');
});
QUnit.test('listenTo and stopListening with event maps', function(assert) {
assert.expect(4);
test("listenTo and stopListening with event maps", 4, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var cb = function(){ assert.ok(true); };
var cb = function(){ ok(true); };
a.listenTo(b, {event: cb});
b.trigger('event');
a.listenTo(b, {event2: cb});
@@ -141,11 +108,10 @@
b.trigger('event event2');
});
QUnit.test('stopListening with omitted args', function(assert) {
assert.expect(2);
test("stopListening with omitted args", 2, function () {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var cb = function() { assert.ok(true); };
var cb = function () { ok(true); };
a.listenTo(b, 'event', cb);
b.on('event', cb);
a.listenTo(b, 'event2', cb);
@@ -158,237 +124,219 @@
b.trigger('event2');
});
QUnit.test('listenToOnce', function(assert) {
assert.expect(2);
test("listenToOnce", 2, function() {
// Same as the previous test, but we use once rather than having to explicitly unbind
var obj = {counterA: 0, counterB: 0};
var obj = { counterA: 0, counterB: 0 };
_.extend(obj, Backbone.Events);
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
var incrB = function(){ obj.counterB += 1; };
obj.listenToOnce(obj, 'event', incrA);
obj.listenToOnce(obj, 'event', incrB);
obj.trigger('event');
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
});
QUnit.test('listenToOnce and stopListening', function(assert) {
assert.expect(1);
test("listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { assert.ok(true); });
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenToOnce(b, 'all', function() { assert.ok(false); });
a.listenToOnce(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
QUnit.test('listenTo, listenToOnce and stopListening', function(assert) {
assert.expect(1);
test("listenTo, listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { assert.ok(true); });
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenTo(b, 'all', function() { assert.ok(false); });
a.listenTo(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
QUnit.test('listenTo and stopListening with event maps', function(assert) {
assert.expect(1);
test("listenTo and stopListening with event maps", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, {change: function(){ assert.ok(true); }});
a.listenTo(b, {change: function(){ ok(true); }});
b.trigger('change');
a.listenTo(b, {change: function(){ assert.ok(false); }});
a.listenTo(b, {change: function(){ ok(false); }});
a.stopListening();
b.trigger('change');
});
QUnit.test('listenTo yourself', function(assert) {
assert.expect(1);
test("listenTo yourself", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, 'foo', function(){ assert.ok(true); });
e.trigger('foo');
e.listenTo(e, "foo", function(){ ok(true); });
e.trigger("foo");
});
QUnit.test('listenTo yourself cleans yourself up with stopListening', function(assert) {
assert.expect(1);
test("listenTo yourself cleans yourself up with stopListening", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, 'foo', function(){ assert.ok(true); });
e.trigger('foo');
e.listenTo(e, "foo", function(){ ok(true); });
e.trigger("foo");
e.stopListening();
e.trigger('foo');
e.trigger("foo");
});
QUnit.test('stopListening cleans up references', function(assert) {
assert.expect(12);
test("stopListening cleans up references", 12, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var fn = function() {};
b.on('event', fn);
a.listenTo(b, 'event', fn).stopListening();
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn).stopListening(b);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn).stopListening(b, 'event');
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn).stopListening(b, 'event', fn);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
});
QUnit.test('stopListening cleans up references from listenToOnce', function(assert) {
assert.expect(12);
test("stopListening cleans up references from listenToOnce", 12, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var fn = function() {};
b.on('event', fn);
a.listenToOnce(b, 'event', fn).stopListening();
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenToOnce(b, 'event', fn).stopListening(b);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenToOnce(b, 'event', fn).stopListening(b, 'event');
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
a.listenToOnce(b, 'event', fn).stopListening(b, 'event', fn);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._events.event), 1);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._events.event), 1);
equal(_.size(b._listeners), 0);
});
QUnit.test('listenTo and off cleaning up references', function(assert) {
assert.expect(8);
test("listenTo and off cleaning up references", 8, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var fn = function() {};
a.listenTo(b, 'event', fn);
b.off();
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn);
b.off('event');
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn);
b.off(null, fn);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._listeners), 0);
a.listenTo(b, 'event', fn);
b.off(null, null, a);
assert.equal(_.size(a._listeningTo), 0);
assert.equal(_.size(b._listeners), 0);
equal(_.size(a._listeningTo), 0);
equal(_.size(b._listeners), 0);
});
QUnit.test('listenTo and stopListening cleaning up references', function(assert) {
assert.expect(2);
test("listenTo and stopListening cleaning up references", 2, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, 'all', function(){ assert.ok(true); });
a.listenTo(b, 'all', function(){ ok(true); });
b.trigger('anything');
a.listenTo(b, 'other', function(){ assert.ok(false); });
a.listenTo(b, 'other', function(){ ok(false); });
a.stopListening(b, 'other');
a.stopListening(b, 'all');
assert.equal(_.size(a._listeningTo), 0);
equal(_.size(a._listeningTo), 0);
});
QUnit.test('listenToOnce without context cleans up references after the event has fired', function(assert) {
assert.expect(2);
test("listenToOnce without context cleans up references after the event has fired", 2, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function(){ assert.ok(true); });
a.listenToOnce(b, 'all', function(){ ok(true); });
b.trigger('anything');
assert.equal(_.size(a._listeningTo), 0);
equal(_.size(a._listeningTo), 0);
});
QUnit.test('listenToOnce with event maps cleans up references', function(assert) {
assert.expect(2);
test("listenToOnce with event maps cleans up references", 2, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, {
one: function() { assert.ok(true); },
two: function() { assert.ok(false); }
one: function() { ok(true); },
two: function() { ok(false); }
});
b.trigger('one');
assert.equal(_.size(a._listeningTo), 1);
equal(_.size(a._listeningTo), 1);
});
QUnit.test('listenToOnce with event maps binds the correct `this`', function(assert) {
assert.expect(1);
test("listenToOnce with event maps binds the correct `this`", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, {
one: function() { assert.ok(this === a); },
two: function() { assert.ok(false); }
one: function() { ok(this === a); },
two: function() { ok(false); }
});
b.trigger('one');
});
QUnit.test("listenTo with empty callback doesn't throw an error", function(assert) {
assert.expect(1);
test("listenTo with empty callback doesn't throw an error", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, 'foo', null);
e.trigger('foo');
assert.ok(true);
e.listenTo(e, "foo", null);
e.trigger("foo");
ok(true);
});
QUnit.test('trigger all for each event', function(assert) {
assert.expect(3);
var a, b, obj = {counter: 0};
test("trigger all for each event", 3, function() {
var a, b, obj = { counter: 0 };
_.extend(obj, Backbone.Events);
obj.on('all', function(event) {
obj.counter++;
if (event === 'a') a = true;
if (event === 'b') b = true;
if (event == 'a') a = true;
if (event == 'b') b = true;
})
.trigger('a b');
assert.ok(a);
assert.ok(b);
assert.equal(obj.counter, 2);
ok(a);
ok(b);
equal(obj.counter, 2);
});
QUnit.test('on, then unbind all functions', function(assert) {
assert.expect(1);
var obj = {counter: 0};
_.extend(obj, Backbone.Events);
test("on, then unbind all functions", 1, function() {
var obj = { counter: 0 };
_.extend(obj,Backbone.Events);
var callback = function() { obj.counter += 1; };
obj.on('event', callback);
obj.trigger('event');
obj.off('event');
obj.trigger('event');
assert.equal(obj.counter, 1, 'counter should have only been incremented once.');
equal(obj.counter, 1, 'counter should have only been incremented once.');
});
QUnit.test('bind two callbacks, unbind only one', function(assert) {
assert.expect(2);
var obj = {counterA: 0, counterB: 0};
_.extend(obj, Backbone.Events);
test("bind two callbacks, unbind only one", 2, function() {
var obj = { counterA: 0, counterB: 0 };
_.extend(obj,Backbone.Events);
var callback = function() { obj.counterA += 1; };
obj.on('event', callback);
obj.on('event', function() { obj.counterB += 1; });
obj.trigger('event');
obj.off('event', callback);
obj.trigger('event');
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
assert.equal(obj.counterB, 2, 'counterB should have been incremented twice.');
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
equal(obj.counterB, 2, 'counterB should have been incremented twice.');
});
QUnit.test('unbind a callback in the midst of it firing', function(assert) {
assert.expect(1);
test("unbind a callback in the midst of it firing", 1, function() {
var obj = {counter: 0};
_.extend(obj, Backbone.Events);
var callback = function() {
@@ -399,13 +347,12 @@
obj.trigger('event');
obj.trigger('event');
obj.trigger('event');
assert.equal(obj.counter, 1, 'the callback should have been unbound.');
equal(obj.counter, 1, 'the callback should have been unbound.');
});
QUnit.test('two binds that unbind themeselves', function(assert) {
assert.expect(2);
var obj = {counterA: 0, counterB: 0};
_.extend(obj, Backbone.Events);
test("two binds that unbind themeselves", 2, function() {
var obj = { counterA: 0, counterB: 0 };
_.extend(obj,Backbone.Events);
var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
var incrB = function(){ obj.counterB += 1; obj.off('event', incrB); };
obj.on('event', incrA);
@@ -413,64 +360,48 @@
obj.trigger('event');
obj.trigger('event');
obj.trigger('event');
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
});
QUnit.test('bind a callback with a default context when none supplied', function(assert) {
assert.expect(1);
var obj = _.extend({
assertTrue: function() {
assert.equal(this, obj, '`this` was bound to the callback');
}
}, Backbone.Events);
obj.once('event', obj.assertTrue);
obj.trigger('event');
});
QUnit.test('bind a callback with a supplied context', function(assert) {
assert.expect(1);
var TestClass = function() {
test("bind a callback with a supplied context", 1, function () {
var TestClass = function () {
return this;
};
TestClass.prototype.assertTrue = function() {
assert.ok(true, '`this` was bound to the callback');
TestClass.prototype.assertTrue = function () {
ok(true, '`this` was bound to the callback');
};
var obj = _.extend({}, Backbone.Events);
obj.on('event', function() { this.assertTrue(); }, new TestClass);
var obj = _.extend({},Backbone.Events);
obj.on('event', function () { this.assertTrue(); }, (new TestClass));
obj.trigger('event');
});
QUnit.test('nested trigger with unbind', function(assert) {
assert.expect(1);
var obj = {counter: 0};
test("nested trigger with unbind", 1, function () {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
var incr2 = function(){ obj.counter += 1; };
obj.on('event', incr1);
obj.on('event', incr2);
obj.trigger('event');
assert.equal(obj.counter, 3, 'counter should have been incremented three times');
equal(obj.counter, 3, 'counter should have been incremented three times');
});
QUnit.test('callback list is not altered during trigger', function(assert) {
assert.expect(2);
test("callback list is not altered during trigger", 2, function () {
var counter = 0, obj = _.extend({}, Backbone.Events);
var incr = function(){ counter++; };
var incrOn = function(){ obj.on('event all', incr); };
var incrOff = function(){ obj.off('event all', incr); };
obj.on('event all', incrOn).trigger('event');
assert.equal(counter, 0, 'on does not alter callback list');
equal(counter, 0, 'on does not alter callback list');
obj.off().on('event', incrOff).on('event all', incr).trigger('event');
assert.equal(counter, 2, 'off does not alter callback list');
equal(counter, 2, 'off does not alter callback list');
});
QUnit.test("#1282 - 'all' callback list is retrieved after each event.", function(assert) {
assert.expect(1);
test("#1282 - 'all' callback list is retrieved after each event.", 1, function() {
var counter = 0;
var obj = _.extend({}, Backbone.Events);
var incr = function(){ counter++; };
@@ -478,68 +409,61 @@
obj.on('y', incr).on('all', incr);
})
.trigger('x y');
assert.strictEqual(counter, 2);
strictEqual(counter, 2);
});
QUnit.test('if no callback is provided, `on` is a noop', function(assert) {
assert.expect(0);
test("if no callback is provided, `on` is a noop", 0, function() {
_.extend({}, Backbone.Events).on('test').trigger('test');
});
QUnit.test('if callback is truthy but not a function, `on` should throw an error just like jQuery', function(assert) {
assert.expect(1);
test("if callback is truthy but not a function, `on` should throw an error just like jQuery", 1, function() {
var view = _.extend({}, Backbone.Events).on('test', 'noop');
assert.raises(function() {
throws(function() {
view.trigger('test');
});
});
QUnit.test('remove all events for a specific context', function(assert) {
assert.expect(4);
test("remove all events for a specific context", 4, function() {
var obj = _.extend({}, Backbone.Events);
obj.on('x y all', function() { assert.ok(true); });
obj.on('x y all', function() { assert.ok(false); }, obj);
obj.on('x y all', function() { ok(true); });
obj.on('x y all', function() { ok(false); }, obj);
obj.off(null, null, obj);
obj.trigger('x y');
});
QUnit.test('remove all events for a specific callback', function(assert) {
assert.expect(4);
test("remove all events for a specific callback", 4, function() {
var obj = _.extend({}, Backbone.Events);
var success = function() { assert.ok(true); };
var fail = function() { assert.ok(false); };
var success = function() { ok(true); };
var fail = function() { ok(false); };
obj.on('x y all', success);
obj.on('x y all', fail);
obj.off(null, fail);
obj.trigger('x y');
});
QUnit.test('#1310 - off does not skip consecutive events', function(assert) {
assert.expect(0);
test("#1310 - off does not skip consecutive events", 0, function() {
var obj = _.extend({}, Backbone.Events);
obj.on('event', function() { assert.ok(false); }, obj);
obj.on('event', function() { assert.ok(false); }, obj);
obj.on('event', function() { ok(false); }, obj);
obj.on('event', function() { ok(false); }, obj);
obj.off(null, null, obj);
obj.trigger('event');
});
QUnit.test('once', function(assert) {
assert.expect(2);
test("once", 2, function() {
// Same as the previous test, but we use once rather than having to explicitly unbind
var obj = {counterA: 0, counterB: 0};
var obj = { counterA: 0, counterB: 0 };
_.extend(obj, Backbone.Events);
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
var incrB = function(){ obj.counterB += 1; };
obj.once('event', incrA);
obj.once('event', incrB);
obj.trigger('event');
assert.equal(obj.counterA, 1, 'counterA should have only been incremented once.');
assert.equal(obj.counterB, 1, 'counterB should have only been incremented once.');
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
});
QUnit.test('once variant one', function(assert) {
assert.expect(3);
var f = function(){ assert.ok(true); };
test("once variant one", 3, function() {
var f = function(){ ok(true); };
var a = _.extend({}, Backbone.Events).once('event', f);
var b = _.extend({}, Backbone.Events).on('event', f);
@@ -550,9 +474,8 @@
b.trigger('event');
});
QUnit.test('once variant two', function(assert) {
assert.expect(3);
var f = function(){ assert.ok(true); };
test("once variant two", 3, function() {
var f = function(){ ok(true); };
var obj = _.extend({}, Backbone.Events);
obj
@@ -562,9 +485,8 @@
.trigger('event');
});
QUnit.test('once with off', function(assert) {
assert.expect(0);
var f = function(){ assert.ok(true); };
test("once with off", 0, function() {
var f = function(){ ok(true); };
var obj = _.extend({}, Backbone.Events);
obj.once('event', f);
@@ -572,8 +494,8 @@
obj.trigger('event');
});
QUnit.test('once with event maps', function(assert) {
var obj = {counter: 0};
test("once with event maps", function() {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
var increment = function() {
@@ -587,120 +509,98 @@
}, obj);
obj.trigger('a');
assert.equal(obj.counter, 1);
equal(obj.counter, 1);
obj.trigger('a b');
assert.equal(obj.counter, 2);
equal(obj.counter, 2);
obj.trigger('c');
assert.equal(obj.counter, 3);
equal(obj.counter, 3);
obj.trigger('a b c');
assert.equal(obj.counter, 3);
equal(obj.counter, 3);
});
QUnit.test('bind a callback with a supplied context using once with object notation', function(assert) {
assert.expect(1);
var obj = {counter: 0};
var context = {};
_.extend(obj, Backbone.Events);
obj.once({
a: function() {
assert.strictEqual(this, context, 'defaults `context` to `callback` param');
}
}, context).trigger('a');
});
QUnit.test('once with off only by context', function(assert) {
assert.expect(0);
test("once with off only by context", 0, function() {
var context = {};
var obj = _.extend({}, Backbone.Events);
obj.once('event', function(){ assert.ok(false); }, context);
obj.once('event', function(){ ok(false); }, context);
obj.off(null, null, context);
obj.trigger('event');
});
QUnit.test('Backbone object inherits Events', function(assert) {
assert.ok(Backbone.on === Backbone.Events.on);
test("Backbone object inherits Events", function() {
ok(Backbone.on === Backbone.Events.on);
});
QUnit.test('once with asynchronous events', function(assert) {
var done = assert.async();
assert.expect(1);
var func = _.debounce(function() { assert.ok(true); done(); }, 50);
asyncTest("once with asynchronous events", 1, function() {
var func = _.debounce(function() { ok(true); start(); }, 50);
var obj = _.extend({}, Backbone.Events).once('async', func);
obj.trigger('async');
obj.trigger('async');
});
QUnit.test('once with multiple events.', function(assert) {
assert.expect(2);
test("once with multiple events.", 2, function() {
var obj = _.extend({}, Backbone.Events);
obj.once('x y', function() { assert.ok(true); });
obj.once('x y', function() { ok(true); });
obj.trigger('x y');
});
QUnit.test('Off during iteration with once.', function(assert) {
assert.expect(2);
test("Off during iteration with once.", 2, function() {
var obj = _.extend({}, Backbone.Events);
var f = function(){ this.off('event', f); };
obj.on('event', f);
obj.once('event', function(){});
obj.on('event', function(){ assert.ok(true); });
obj.on('event', function(){ ok(true); });
obj.trigger('event');
obj.trigger('event');
});
QUnit.test('`once` on `all` should work as expected', function(assert) {
assert.expect(1);
test("`once` on `all` should work as expected", 1, function() {
Backbone.once('all', function() {
assert.ok(true);
ok(true);
Backbone.trigger('all');
});
Backbone.trigger('all');
});
QUnit.test('once without a callback is a noop', function(assert) {
assert.expect(0);
test("once without a callback is a noop", 0, function() {
_.extend({}, Backbone.Events).once('event').trigger('event');
});
QUnit.test('listenToOnce without a callback is a noop', function(assert) {
assert.expect(0);
test("listenToOnce without a callback is a noop", 0, function() {
var obj = _.extend({}, Backbone.Events);
obj.listenToOnce(obj, 'event').trigger('event');
});
QUnit.test('event functions are chainable', function(assert) {
test("event functions are chainable", function() {
var obj = _.extend({}, Backbone.Events);
var obj2 = _.extend({}, Backbone.Events);
var fn = function() {};
assert.equal(obj, obj.trigger('noeventssetyet'));
assert.equal(obj, obj.off('noeventssetyet'));
assert.equal(obj, obj.stopListening('noeventssetyet'));
assert.equal(obj, obj.on('a', fn));
assert.equal(obj, obj.once('c', fn));
assert.equal(obj, obj.trigger('a'));
assert.equal(obj, obj.listenTo(obj2, 'a', fn));
assert.equal(obj, obj.listenToOnce(obj2, 'b', fn));
assert.equal(obj, obj.off('a c'));
assert.equal(obj, obj.stopListening(obj2, 'a'));
assert.equal(obj, obj.stopListening());
equal(obj, obj.trigger('noeventssetyet'));
equal(obj, obj.off('noeventssetyet'));
equal(obj, obj.stopListening('noeventssetyet'));
equal(obj, obj.on('a', fn));
equal(obj, obj.once('c', fn));
equal(obj, obj.trigger('a'));
equal(obj, obj.listenTo(obj2, 'a', fn));
equal(obj, obj.listenToOnce(obj2, 'b', fn));
equal(obj, obj.off('a c'));
equal(obj, obj.stopListening(obj2, 'a'));
equal(obj, obj.stopListening());
});
QUnit.test('#3448 - listenToOnce with space-separated events', function(assert) {
assert.expect(2);
test("#3448 - listenToOnce with space-separated events", 2, function() {
var one = _.extend({}, Backbone.Events);
var two = _.extend({}, Backbone.Events);
var count = 1;
one.listenToOnce(two, 'x y', function(n) { assert.ok(n === count++); });
one.listenToOnce(two, 'x y', function(n) { ok(n === count++); });
two.trigger('x', 1);
two.trigger('x', 1);
two.trigger('y', 2);
two.trigger('y', 2);
});
})(QUnit);
})();

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,12 @@
(function(QUnit) {
(function() {
QUnit.module('Backbone.noConflict');
module("Backbone.noConflict");
QUnit.test('noConflict', function(assert) {
assert.expect(2);
test('noConflict', 2, function() {
var noconflictBackbone = Backbone.noConflict();
assert.equal(window.Backbone, undefined, 'Returned window.Backbone');
equal(window.Backbone, undefined, 'Returned window.Backbone');
window.Backbone = noconflictBackbone;
assert.equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
});
})(QUnit);
})();

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
$('body').append(
'<div id="qunit"></div>' +
'<div id="qunit-fixture"></div>'
);
'<div id="qunit-fixture">' +
'<div id="testElement"><h1>Test</h1></div>' +
'</div>'
);

View File

@@ -1,4 +1,4 @@
(function(QUnit) {
(function() {
var sync = Backbone.sync;
var ajax = Backbone.ajax;
@@ -8,13 +8,11 @@
var pushState = history.pushState;
var replaceState = history.replaceState;
QUnit.config.noglobals = true;
QUnit.testStart(function() {
var env = QUnit.config.current.testEnvironment;
// We never want to actually call these during tests.
history.pushState = history.replaceState = function() {};
history.pushState = history.replaceState = function(){};
// Capture ajax settings for comparison.
Backbone.ajax = function(settings) {
@@ -42,4 +40,4 @@
history.replaceState = replaceState;
});
})(QUnit);
})();

View File

@@ -1,239 +1,221 @@
(function(QUnit) {
(function() {
var Library = Backbone.Collection.extend({
url: function() { return '/library'; }
url : function() { return '/library'; }
});
var library;
var attrs = {
title: 'The Tempest',
author: 'Bill Shakespeare',
length: 123
title : "The Tempest",
author : "Bill Shakespeare",
length : 123
};
QUnit.module('Backbone.sync', {
module("Backbone.sync", {
beforeEach: function(assert) {
setup : function() {
library = new Library;
library.create(attrs, {wait: false});
},
afterEach: function(assert) {
teardown: function() {
Backbone.emulateHTTP = false;
}
});
QUnit.test('read', function(assert) {
assert.expect(4);
test("read", 4, function() {
library.fetch();
assert.equal(this.ajaxSettings.url, '/library');
assert.equal(this.ajaxSettings.type, 'GET');
assert.equal(this.ajaxSettings.dataType, 'json');
assert.ok(_.isEmpty(this.ajaxSettings.data));
equal(this.ajaxSettings.url, '/library');
equal(this.ajaxSettings.type, 'GET');
equal(this.ajaxSettings.dataType, 'json');
ok(_.isEmpty(this.ajaxSettings.data));
});
QUnit.test('passing data', function(assert) {
assert.expect(3);
test("passing data", 3, function() {
library.fetch({data: {a: 'a', one: 1}});
assert.equal(this.ajaxSettings.url, '/library');
assert.equal(this.ajaxSettings.data.a, 'a');
assert.equal(this.ajaxSettings.data.one, 1);
equal(this.ajaxSettings.url, '/library');
equal(this.ajaxSettings.data.a, 'a');
equal(this.ajaxSettings.data.one, 1);
});
QUnit.test('create', function(assert) {
assert.expect(6);
assert.equal(this.ajaxSettings.url, '/library');
assert.equal(this.ajaxSettings.type, 'POST');
assert.equal(this.ajaxSettings.dataType, 'json');
test("create", 6, function() {
equal(this.ajaxSettings.url, '/library');
equal(this.ajaxSettings.type, 'POST');
equal(this.ajaxSettings.dataType, 'json');
var data = JSON.parse(this.ajaxSettings.data);
assert.equal(data.title, 'The Tempest');
assert.equal(data.author, 'Bill Shakespeare');
assert.equal(data.length, 123);
equal(data.title, 'The Tempest');
equal(data.author, 'Bill Shakespeare');
equal(data.length, 123);
});
QUnit.test('update', function(assert) {
assert.expect(7);
test("update", 7, function() {
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
assert.equal(this.ajaxSettings.url, '/library/1-the-tempest');
assert.equal(this.ajaxSettings.type, 'PUT');
assert.equal(this.ajaxSettings.dataType, 'json');
equal(this.ajaxSettings.url, '/library/1-the-tempest');
equal(this.ajaxSettings.type, 'PUT');
equal(this.ajaxSettings.dataType, 'json');
var data = JSON.parse(this.ajaxSettings.data);
assert.equal(data.id, '1-the-tempest');
assert.equal(data.title, 'The Tempest');
assert.equal(data.author, 'William Shakespeare');
assert.equal(data.length, 123);
equal(data.id, '1-the-tempest');
equal(data.title, 'The Tempest');
equal(data.author, 'William Shakespeare');
equal(data.length, 123);
});
QUnit.test('update with emulateHTTP and emulateJSON', function(assert) {
assert.expect(7);
test("update with emulateHTTP and emulateJSON", 7, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
emulateHTTP: true,
emulateJSON: true
});
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'POST');
assert.equal(this.ajaxSettings.dataType, 'json');
assert.equal(this.ajaxSettings.data._method, 'PUT');
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'POST');
equal(this.ajaxSettings.dataType, 'json');
equal(this.ajaxSettings.data._method, 'PUT');
var data = JSON.parse(this.ajaxSettings.data.model);
assert.equal(data.id, '2-the-tempest');
assert.equal(data.author, 'Tim Shakespeare');
assert.equal(data.length, 123);
equal(data.id, '2-the-tempest');
equal(data.author, 'Tim Shakespeare');
equal(data.length, 123);
});
QUnit.test('update with just emulateHTTP', function(assert) {
assert.expect(6);
test("update with just emulateHTTP", 6, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
emulateHTTP: true
});
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'POST');
assert.equal(this.ajaxSettings.contentType, 'application/json');
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'POST');
equal(this.ajaxSettings.contentType, 'application/json');
var data = JSON.parse(this.ajaxSettings.data);
assert.equal(data.id, '2-the-tempest');
assert.equal(data.author, 'Tim Shakespeare');
assert.equal(data.length, 123);
equal(data.id, '2-the-tempest');
equal(data.author, 'Tim Shakespeare');
equal(data.length, 123);
});
QUnit.test('update with just emulateJSON', function(assert) {
assert.expect(6);
test("update with just emulateJSON", 6, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
emulateJSON: true
});
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'PUT');
assert.equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded');
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'PUT');
equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded');
var data = JSON.parse(this.ajaxSettings.data.model);
assert.equal(data.id, '2-the-tempest');
assert.equal(data.author, 'Tim Shakespeare');
assert.equal(data.length, 123);
equal(data.id, '2-the-tempest');
equal(data.author, 'Tim Shakespeare');
equal(data.length, 123);
});
QUnit.test('read model', function(assert) {
assert.expect(3);
test("read model", 3, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
library.first().fetch();
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'GET');
assert.ok(_.isEmpty(this.ajaxSettings.data));
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'GET');
ok(_.isEmpty(this.ajaxSettings.data));
});
QUnit.test('destroy', function(assert) {
assert.expect(3);
test("destroy", 3, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
library.first().destroy({wait: true});
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'DELETE');
assert.equal(this.ajaxSettings.data, null);
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'DELETE');
equal(this.ajaxSettings.data, null);
});
QUnit.test('destroy with emulateHTTP', function(assert) {
assert.expect(3);
test("destroy with emulateHTTP", 3, function() {
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
library.first().destroy({
emulateHTTP: true,
emulateJSON: true
});
assert.equal(this.ajaxSettings.url, '/library/2-the-tempest');
assert.equal(this.ajaxSettings.type, 'POST');
assert.equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}');
equal(this.ajaxSettings.url, '/library/2-the-tempest');
equal(this.ajaxSettings.type, 'POST');
equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}');
});
QUnit.test('urlError', function(assert) {
assert.expect(2);
test("urlError", 2, function() {
var model = new Backbone.Model();
assert.raises(function() {
throws(function() {
model.fetch();
});
model.fetch({url: '/one/two'});
assert.equal(this.ajaxSettings.url, '/one/two');
equal(this.ajaxSettings.url, '/one/two');
});
QUnit.test('#1052 - `options` is optional.', function(assert) {
assert.expect(0);
test("#1052 - `options` is optional.", 0, function() {
var model = new Backbone.Model();
model.url = '/test';
Backbone.sync('create', model);
});
QUnit.test('Backbone.ajax', function(assert) {
assert.expect(1);
Backbone.ajax = function(settings) {
assert.strictEqual(settings.url, '/test');
test("Backbone.ajax", 1, function() {
Backbone.ajax = function(settings){
strictEqual(settings.url, '/test');
};
var model = new Backbone.Model();
model.url = '/test';
Backbone.sync('create', model);
});
QUnit.test('Call provided error callback on error.', function(assert) {
assert.expect(1);
test("Call provided error callback on error.", 1, function() {
var model = new Backbone.Model;
model.url = '/test';
Backbone.sync('read', model, {
error: function() { assert.ok(true); }
error: function() { ok(true); }
});
this.ajaxSettings.error();
});
QUnit.test('Use Backbone.emulateHTTP as default.', function(assert) {
assert.expect(2);
test('Use Backbone.emulateHTTP as default.', 2, function() {
var model = new Backbone.Model;
model.url = '/test';
Backbone.emulateHTTP = true;
model.sync('create', model);
assert.strictEqual(this.ajaxSettings.emulateHTTP, true);
strictEqual(this.ajaxSettings.emulateHTTP, true);
Backbone.emulateHTTP = false;
model.sync('create', model);
assert.strictEqual(this.ajaxSettings.emulateHTTP, false);
strictEqual(this.ajaxSettings.emulateHTTP, false);
});
QUnit.test('Use Backbone.emulateJSON as default.', function(assert) {
assert.expect(2);
test('Use Backbone.emulateJSON as default.', 2, function() {
var model = new Backbone.Model;
model.url = '/test';
Backbone.emulateJSON = true;
model.sync('create', model);
assert.strictEqual(this.ajaxSettings.emulateJSON, true);
strictEqual(this.ajaxSettings.emulateJSON, true);
Backbone.emulateJSON = false;
model.sync('create', model);
assert.strictEqual(this.ajaxSettings.emulateJSON, false);
strictEqual(this.ajaxSettings.emulateJSON, false);
});
QUnit.test('#1756 - Call user provided beforeSend function.', function(assert) {
assert.expect(4);
test("#1756 - Call user provided beforeSend function.", 4, function() {
Backbone.emulateHTTP = true;
var model = new Backbone.Model;
model.url = '/test';
var xhr = {
setRequestHeader: function(header, value) {
assert.strictEqual(header, 'X-HTTP-Method-Override');
assert.strictEqual(value, 'DELETE');
strictEqual(header, 'X-HTTP-Method-Override');
strictEqual(value, 'DELETE');
}
};
model.sync('delete', model, {
beforeSend: function(_xhr) {
assert.ok(_xhr === xhr);
ok(_xhr === xhr);
return false;
}
});
assert.strictEqual(this.ajaxSettings.beforeSend(xhr), false);
strictEqual(this.ajaxSettings.beforeSend(xhr), false);
});
QUnit.test('#2928 - Pass along `textStatus` and `errorThrown`.', function(assert) {
assert.expect(2);
test('#2928 - Pass along `textStatus` and `errorThrown`.', 2, function() {
var model = new Backbone.Model;
model.url = '/test';
model.on('error', function(m, xhr, options) {
assert.strictEqual(options.textStatus, 'textStatus');
assert.strictEqual(options.errorThrown, 'errorThrown');
model.on('error', function(model, xhr, options) {
strictEqual(options.textStatus, 'textStatus');
strictEqual(options.errorThrown, 'errorThrown');
});
model.fetch();
this.ajaxSettings.error({}, 'textStatus', 'errorThrown');
});
})(QUnit);
})();

View File

@@ -1,137 +1,98 @@
(function(QUnit) {
(function() {
var view;
QUnit.module('Backbone.View', {
beforeEach: function() {
$('#qunit-fixture').append(
'<div id="testElement"><h1>Test</h1></div>'
);
module("Backbone.View", {
setup: function() {
view = new Backbone.View({
id: 'test-view',
className: 'test-view',
other: 'non-special-option'
id : 'test-view',
className : 'test-view',
other : 'non-special-option'
});
},
afterEach: function() {
$('#testElement').remove();
$('#test-view').remove();
}
});
QUnit.test('constructor', function(assert) {
assert.expect(3);
assert.equal(view.el.id, 'test-view');
assert.equal(view.el.className, 'test-view');
assert.equal(view.el.other, void 0);
test("constructor", 3, function() {
equal(view.el.id, 'test-view');
equal(view.el.className, 'test-view');
equal(view.el.other, void 0);
});
QUnit.test('$', function(assert) {
assert.expect(2);
var myView = new Backbone.View;
myView.setElement('<p><a><b>test</b></a></p>');
var result = myView.$('a b');
test("$", 2, function() {
var view = new Backbone.View;
view.setElement('<p><a><b>test</b></a></p>');
var result = view.$('a b');
assert.strictEqual(result[0].innerHTML, 'test');
assert.ok(result.length === +result.length);
strictEqual(result[0].innerHTML, 'test');
ok(result.length === +result.length);
});
QUnit.test('$el', function(assert) {
assert.expect(3);
var myView = new Backbone.View;
myView.setElement('<p><a><b>test</b></a></p>');
assert.strictEqual(myView.el.nodeType, 1);
test("$el", 3, function() {
var view = new Backbone.View;
view.setElement('<p><a><b>test</b></a></p>');
strictEqual(view.el.nodeType, 1);
assert.ok(myView.$el instanceof Backbone.$);
assert.strictEqual(myView.$el[0], myView.el);
ok(view.$el instanceof Backbone.$);
strictEqual(view.$el[0], view.el);
});
QUnit.test('initialize', function(assert) {
assert.expect(1);
test("initialize", 1, function() {
var View = Backbone.View.extend({
initialize: function() {
this.one = 1;
}
});
assert.strictEqual(new View().one, 1);
strictEqual(new View().one, 1);
});
QUnit.test('preinitialize', function(assert) {
assert.expect(1);
var View = Backbone.View.extend({
preinitialize: function() {
this.one = 1;
}
});
assert.strictEqual(new View().one, 1);
test("render", 1, function() {
var view = new Backbone.View;
equal(view.render(), view, '#render returns the view instance');
});
QUnit.test('preinitialize occurs before the view is set up', function(assert) {
assert.expect(2);
var View = Backbone.View.extend({
preinitialize: function() {
assert.equal(this.el, undefined);
}
});
var _view = new View({});
assert.notEqual(_view.el, undefined);
});
QUnit.test('render', function(assert) {
assert.expect(1);
var myView = new Backbone.View;
assert.equal(myView.render(), myView, '#render returns the view instance');
});
QUnit.test('delegateEvents', function(assert) {
assert.expect(6);
test("delegateEvents", 6, function() {
var counter1 = 0, counter2 = 0;
var myView = new Backbone.View({el: '#testElement'});
myView.increment = function() { counter1++; };
myView.$el.on('click', function() { counter2++; });
var view = new Backbone.View({el: '#testElement'});
view.increment = function(){ counter1++; };
view.$el.on('click', function(){ counter2++; });
var events = {'click h1': 'increment'};
myView.delegateEvents(events);
myView.$('h1').trigger('click');
assert.equal(counter1, 1);
assert.equal(counter2, 1);
view.delegateEvents(events);
view.$('h1').trigger('click');
equal(counter1, 1);
equal(counter2, 1);
myView.$('h1').trigger('click');
assert.equal(counter1, 2);
assert.equal(counter2, 2);
view.$('h1').trigger('click');
equal(counter1, 2);
equal(counter2, 2);
myView.delegateEvents(events);
myView.$('h1').trigger('click');
assert.equal(counter1, 3);
assert.equal(counter2, 3);
view.delegateEvents(events);
view.$('h1').trigger('click');
equal(counter1, 3);
equal(counter2, 3);
});
QUnit.test('delegate', function(assert) {
assert.expect(3);
var myView = new Backbone.View({el: '#testElement'});
myView.delegate('click', 'h1', function() {
assert.ok(true);
test("delegate", 3, function() {
var view = new Backbone.View({el: '#testElement'});
view.delegate('click', 'h1', function() {
ok(true);
});
myView.delegate('click', function() {
assert.ok(true);
view.delegate('click', function() {
ok(true);
});
myView.$('h1').trigger('click');
view.$('h1').trigger('click');
assert.equal(myView.delegate(), myView, '#delegate returns the view instance');
equal(view.delegate(), view, '#delegate returns the view instance');
});
QUnit.test('delegateEvents allows functions for callbacks', function(assert) {
assert.expect(3);
var myView = new Backbone.View({el: '<p></p>'});
myView.counter = 0;
test("delegateEvents allows functions for callbacks", 3, function() {
var view = new Backbone.View({el: '<p></p>'});
view.counter = 0;
var events = {
click: function() {
@@ -139,147 +100,137 @@
}
};
myView.delegateEvents(events);
myView.$el.trigger('click');
assert.equal(myView.counter, 1);
view.delegateEvents(events);
view.$el.trigger('click');
equal(view.counter, 1);
myView.$el.trigger('click');
assert.equal(myView.counter, 2);
view.$el.trigger('click');
equal(view.counter, 2);
myView.delegateEvents(events);
myView.$el.trigger('click');
assert.equal(myView.counter, 3);
view.delegateEvents(events);
view.$el.trigger('click');
equal(view.counter, 3);
});
QUnit.test('delegateEvents ignore undefined methods', function(assert) {
assert.expect(0);
var myView = new Backbone.View({el: '<p></p>'});
myView.delegateEvents({click: 'undefinedMethod'});
myView.$el.trigger('click');
test("delegateEvents ignore undefined methods", 0, function() {
var view = new Backbone.View({el: '<p></p>'});
view.delegateEvents({'click': 'undefinedMethod'});
view.$el.trigger('click');
});
QUnit.test('undelegateEvents', function(assert) {
assert.expect(7);
test("undelegateEvents", 7, function() {
var counter1 = 0, counter2 = 0;
var myView = new Backbone.View({el: '#testElement'});
myView.increment = function() { counter1++; };
myView.$el.on('click', function() { counter2++; });
var view = new Backbone.View({el: '#testElement'});
view.increment = function(){ counter1++; };
view.$el.on('click', function(){ counter2++; });
var events = {'click h1': 'increment'};
myView.delegateEvents(events);
myView.$('h1').trigger('click');
assert.equal(counter1, 1);
assert.equal(counter2, 1);
view.delegateEvents(events);
view.$('h1').trigger('click');
equal(counter1, 1);
equal(counter2, 1);
myView.undelegateEvents();
myView.$('h1').trigger('click');
assert.equal(counter1, 1);
assert.equal(counter2, 2);
view.undelegateEvents();
view.$('h1').trigger('click');
equal(counter1, 1);
equal(counter2, 2);
myView.delegateEvents(events);
myView.$('h1').trigger('click');
assert.equal(counter1, 2);
assert.equal(counter2, 3);
view.delegateEvents(events);
view.$('h1').trigger('click');
equal(counter1, 2);
equal(counter2, 3);
assert.equal(myView.undelegateEvents(), myView, '#undelegateEvents returns the view instance');
equal(view.undelegateEvents(), view, '#undelegateEvents returns the view instance');
});
QUnit.test('undelegate', function(assert) {
assert.expect(1);
var myView = new Backbone.View({el: '#testElement'});
myView.delegate('click', function() { assert.ok(false); });
myView.delegate('click', 'h1', function() { assert.ok(false); });
test("undelegate", 1, function() {
view = new Backbone.View({el: '#testElement'});
view.delegate('click', function() { ok(false); });
view.delegate('click', 'h1', function() { ok(false); });
myView.undelegate('click');
view.undelegate('click');
myView.$('h1').trigger('click');
myView.$el.trigger('click');
view.$('h1').trigger('click');
view.$el.trigger('click');
assert.equal(myView.undelegate(), myView, '#undelegate returns the view instance');
equal(view.undelegate(), view, '#undelegate returns the view instance');
});
QUnit.test('undelegate with passed handler', function(assert) {
assert.expect(1);
var myView = new Backbone.View({el: '#testElement'});
var listener = function() { assert.ok(false); };
myView.delegate('click', listener);
myView.delegate('click', function() { assert.ok(true); });
myView.undelegate('click', listener);
myView.$el.trigger('click');
test("undelegate with passed handler", 1, function() {
view = new Backbone.View({el: '#testElement'});
var listener = function() { ok(false); };
view.delegate('click', listener);
view.delegate('click', function() { ok(true); });
view.undelegate('click', listener);
view.$el.trigger('click');
});
QUnit.test('undelegate with selector', function(assert) {
assert.expect(2);
var myView = new Backbone.View({el: '#testElement'});
myView.delegate('click', function() { assert.ok(true); });
myView.delegate('click', 'h1', function() { assert.ok(false); });
myView.undelegate('click', 'h1');
myView.$('h1').trigger('click');
myView.$el.trigger('click');
test("undelegate with selector", 2, function() {
view = new Backbone.View({el: '#testElement'});
view.delegate('click', function() { ok(true); });
view.delegate('click', 'h1', function() { ok(false); });
view.undelegate('click', 'h1');
view.$('h1').trigger('click');
view.$el.trigger('click');
});
QUnit.test('undelegate with handler and selector', function(assert) {
assert.expect(2);
var myView = new Backbone.View({el: '#testElement'});
myView.delegate('click', function() { assert.ok(true); });
var handler = function() { assert.ok(false); };
myView.delegate('click', 'h1', handler);
myView.undelegate('click', 'h1', handler);
myView.$('h1').trigger('click');
myView.$el.trigger('click');
test("undelegate with handler and selector", 2, function() {
view = new Backbone.View({el: '#testElement'});
view.delegate('click', function() { ok(true); });
var handler = function(){ ok(false); };
view.delegate('click', 'h1', handler);
view.undelegate('click', 'h1', handler);
view.$('h1').trigger('click');
view.$el.trigger('click');
});
QUnit.test('tagName can be provided as a string', function(assert) {
assert.expect(1);
test("tagName can be provided as a string", 1, function() {
var View = Backbone.View.extend({
tagName: 'span'
});
assert.equal(new View().el.tagName, 'SPAN');
equal(new View().el.tagName, 'SPAN');
});
QUnit.test('tagName can be provided as a function', function(assert) {
assert.expect(1);
test("tagName can be provided as a function", 1, function() {
var View = Backbone.View.extend({
tagName: function() {
return 'p';
}
});
assert.ok(new View().$el.is('p'));
ok(new View().$el.is('p'));
});
QUnit.test('_ensureElement with DOM node el', function(assert) {
assert.expect(1);
test("_ensureElement with DOM node el", 1, function() {
var View = Backbone.View.extend({
el: document.body
});
assert.equal(new View().el, document.body);
equal(new View().el, document.body);
});
QUnit.test('_ensureElement with string el', function(assert) {
assert.expect(3);
test("_ensureElement with string el", 3, function() {
var View = Backbone.View.extend({
el: 'body'
el: "body"
});
assert.strictEqual(new View().el, document.body);
strictEqual(new View().el, document.body);
View = Backbone.View.extend({
el: '#testElement > h1'
el: "#testElement > h1"
});
assert.strictEqual(new View().el, $('#testElement > h1').get(0));
strictEqual(new View().el, $("#testElement > h1").get(0));
View = Backbone.View.extend({
el: '#nonexistent'
el: "#nonexistent"
});
assert.ok(!new View().el);
ok(!new View().el);
});
QUnit.test('with className and id functions', function(assert) {
assert.expect(2);
test("with className and id functions", 2, function() {
var View = Backbone.View.extend({
className: function() {
return 'className';
@@ -289,54 +240,33 @@
}
});
assert.strictEqual(new View().el.className, 'className');
assert.strictEqual(new View().el.id, 'id');
strictEqual(new View().el.className, 'className');
strictEqual(new View().el.id, 'id');
});
QUnit.test('with attributes', function(assert) {
assert.expect(2);
test("with attributes", 2, function() {
var View = Backbone.View.extend({
attributes: {
'id': 'id',
id: 'id',
'class': 'class'
}
});
assert.strictEqual(new View().el.className, 'class');
assert.strictEqual(new View().el.id, 'id');
strictEqual(new View().el.className, 'class');
strictEqual(new View().el.id, 'id');
});
QUnit.test('with attributes as a function', function(assert) {
assert.expect(1);
test("with attributes as a function", 1, function() {
var View = Backbone.View.extend({
attributes: function() {
return {'class': 'dynamic'};
}
});
assert.strictEqual(new View().el.className, 'dynamic');
strictEqual(new View().el.className, 'dynamic');
});
QUnit.test('should default to className/id properties', function(assert) {
assert.expect(4);
var View = Backbone.View.extend({
className: 'backboneClass',
id: 'backboneId',
attributes: {
'class': 'attributeClass',
'id': 'attributeId'
}
});
var myView = new View;
assert.strictEqual(myView.el.className, 'backboneClass');
assert.strictEqual(myView.el.id, 'backboneId');
assert.strictEqual(myView.$el.attr('class'), 'backboneClass');
assert.strictEqual(myView.$el.attr('id'), 'backboneId');
});
QUnit.test('multiple views per element', function(assert) {
assert.expect(3);
test("multiple views per element", 3, function() {
var count = 0;
var $el = $('<p></p>');
@@ -350,112 +280,105 @@
});
var view1 = new View;
$el.trigger('click');
assert.equal(1, count);
$el.trigger("click");
equal(1, count);
var view2 = new View;
$el.trigger('click');
assert.equal(3, count);
$el.trigger("click");
equal(3, count);
view1.delegateEvents();
$el.trigger('click');
assert.equal(5, count);
$el.trigger("click");
equal(5, count);
});
QUnit.test('custom events', function(assert) {
assert.expect(2);
test("custom events", 2, function() {
var View = Backbone.View.extend({
el: $('body'),
events: {
fake$event: function() { assert.ok(true); }
"fake$event": function() { ok(true); }
}
});
var myView = new View;
var view = new View;
$('body').trigger('fake$event').trigger('fake$event');
$('body').off('fake$event');
$('body').trigger('fake$event');
});
QUnit.test('#1048 - setElement uses provided object.', function(assert) {
assert.expect(2);
test("#1048 - setElement uses provided object.", 2, function() {
var $el = $('body');
var myView = new Backbone.View({el: $el});
assert.ok(myView.$el === $el);
var view = new Backbone.View({el: $el});
ok(view.$el === $el);
myView.setElement($el = $($el));
assert.ok(myView.$el === $el);
view.setElement($el = $($el));
ok(view.$el === $el);
});
QUnit.test('#986 - Undelegate before changing element.', function(assert) {
assert.expect(1);
test("#986 - Undelegate before changing element.", 1, function() {
var button1 = $('<button></button>');
var button2 = $('<button></button>');
var View = Backbone.View.extend({
events: {
click: function(e) {
assert.ok(myView.el === e.target);
ok(view.el === e.target);
}
}
});
var myView = new View({el: button1});
myView.setElement(button2);
var view = new View({el: button1});
view.setElement(button2);
button1.trigger('click');
button2.trigger('click');
});
QUnit.test('#1172 - Clone attributes object', function(assert) {
assert.expect(2);
test("#1172 - Clone attributes object", 2, function() {
var View = Backbone.View.extend({
attributes: {foo: 'bar'}
});
var view1 = new View({id: 'foo'});
assert.strictEqual(view1.el.id, 'foo');
strictEqual(view1.el.id, 'foo');
var view2 = new View();
assert.ok(!view2.el.id);
ok(!view2.el.id);
});
QUnit.test('views stopListening', function(assert) {
assert.expect(0);
test("views stopListening", 0, function() {
var View = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'all x', function() { assert.ok(false); });
this.listenTo(this.collection, 'all x', function() { assert.ok(false); });
this.listenTo(this.model, 'all x', function(){ ok(false); });
this.listenTo(this.collection, 'all x', function(){ ok(false); });
}
});
var myView = new View({
var view = new View({
model: new Backbone.Model,
collection: new Backbone.Collection
});
myView.stopListening();
myView.model.trigger('x');
myView.collection.trigger('x');
view.stopListening();
view.model.trigger('x');
view.collection.trigger('x');
});
QUnit.test('Provide function for el.', function(assert) {
assert.expect(2);
test("Provide function for el.", 2, function() {
var View = Backbone.View.extend({
el: function() {
return '<p><a></a></p>';
return "<p><a></a></p>";
}
});
var myView = new View;
assert.ok(myView.$el.is('p'));
assert.ok(myView.$el.has('a'));
var view = new View;
ok(view.$el.is('p'));
ok(view.$el.has('a'));
});
QUnit.test('events passed in options', function(assert) {
assert.expect(1);
test("events passed in options", 1, function() {
var counter = 0;
var View = Backbone.View.extend({
@@ -465,52 +388,50 @@
}
});
var myView = new View({
var view = new View({
events: {
'click h1': 'increment'
}
});
myView.$('h1').trigger('click').trigger('click');
assert.equal(counter, 2);
view.$('h1').trigger('click').trigger('click');
equal(counter, 2);
});
QUnit.test('remove', function(assert) {
assert.expect(2);
var myView = new Backbone.View;
test("remove", 2, function() {
var view = new Backbone.View;
document.body.appendChild(view.el);
myView.delegate('click', function() { assert.ok(false); });
myView.listenTo(myView, 'all x', function() { assert.ok(false); });
view.delegate('click', function() { ok(false); });
view.listenTo(view, 'all x', function() { ok(false); });
assert.equal(myView.remove(), myView, '#remove returns the view instance');
myView.$el.trigger('click');
myView.trigger('x');
equal(view.remove(), view, '#remove returns the view instance');
view.$el.trigger('click');
view.trigger('x');
// In IE8 and below, parentNode still exists but is not document.body.
assert.notEqual(myView.el.parentNode, document.body);
notEqual(view.el.parentNode, document.body);
});
QUnit.test('setElement', function(assert) {
assert.expect(3);
var myView = new Backbone.View({
test("setElement", 3, function() {
var view = new Backbone.View({
events: {
click: function() { assert.ok(false); }
click: function() { ok(false); }
}
});
myView.events = {
click: function() { assert.ok(true); }
view.events = {
click: function() { ok(true); }
};
var oldEl = myView.el;
var $oldEl = myView.$el;
var oldEl = view.el;
var $oldEl = view.$el;
myView.setElement(document.createElement('div'));
view.setElement(document.createElement('div'));
$oldEl.click();
myView.$el.click();
view.$el.click();
assert.notEqual(oldEl, myView.el);
assert.notEqual($oldEl, myView.$el);
notEqual(oldEl, view.el);
notEqual($oldEl, view.$el);
});
})(QUnit);
})();

22
vendor/benchmark.js/LICENSE vendored Normal file
View File

@@ -0,0 +1,22 @@
Copyright 2010-2015 Mathias Bynens <http://mathiasbynens.be/>
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
Modified by John-David Dalton <http://allyoucanleet.com/>
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.

2875
vendor/benchmark.js/benchmark.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
vendor/benchmark.js/nano.jar vendored Normal file

Binary file not shown.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative
Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors
Permission is hereby granted, free of charge, to any person

View File

@@ -3,407 +3,398 @@
QUnit.module('Arrays');
QUnit.test('first', function(assert) {
assert.equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
assert.equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
assert.deepEqual(_.first([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
assert.deepEqual(_.first([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
assert.deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can fetch the first n elements');
assert.deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
test('first', function() {
equal(_.first([1, 2, 3]), 1, 'can pull out the first element of an array');
equal(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
deepEqual(_.first([1, 2, 3], 0), [], 'can pass an index to first');
deepEqual(_.first([1, 2, 3], 2), [1, 2], 'can pass an index to first');
deepEqual(_.first([1, 2, 3], 5), [1, 2, 3], 'can pass an index to first');
var result = (function(){ return _.first(arguments); }(4, 3, 2, 1));
assert.equal(result, 4, 'works on an arguments object');
equal(result, 4, 'works on an arguments object.');
result = _.map([[1, 2, 3], [1, 2, 3]], _.first);
assert.deepEqual(result, [1, 1], 'works well with _.map');
assert.equal(_.first(null), void 0, 'returns undefined when called on null');
deepEqual(result, [1, 1], 'works well with _.map');
result = (function() { return _.first([1, 2, 3], 2); }());
deepEqual(result, [1, 2]);
Array.prototype[0] = 'boo';
assert.equal(_.first([]), void 0, 'return undefined when called on a empty array');
delete Array.prototype[0];
equal(_.first(null), undefined, 'handles nulls');
strictEqual(_.first([1, 2, 3], -1).length, 0);
});
QUnit.test('head', function(assert) {
assert.strictEqual(_.head, _.first, 'is an alias for first');
test('head', function() {
strictEqual(_.first, _.head, 'alias for first');
});
QUnit.test('take', function(assert) {
assert.strictEqual(_.take, _.first, 'is an alias for first');
test('take', function() {
strictEqual(_.first, _.take, 'alias for first');
});
QUnit.test('rest', function(assert) {
test('rest', function() {
var numbers = [1, 2, 3, 4];
assert.deepEqual(_.rest(numbers), [2, 3, 4], 'fetches all but the first element');
assert.deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'returns the whole array when index is 0');
assert.deepEqual(_.rest(numbers, 2), [3, 4], 'returns elements starting at the given index');
deepEqual(_.rest(numbers), [2, 3, 4], 'working rest()');
deepEqual(_.rest(numbers, 0), [1, 2, 3, 4], 'working rest(0)');
deepEqual(_.rest(numbers, 2), [3, 4], 'rest can take an index');
var result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
deepEqual(result, [2, 3, 4], 'works on arguments object');
result = _.map([[1, 2, 3], [1, 2, 3]], _.rest);
assert.deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
deepEqual(_.flatten(result), [2, 3, 2, 3], 'works well with _.map');
result = (function(){ return _(arguments).rest(); }(1, 2, 3, 4));
deepEqual(result, [2, 3, 4], 'works on arguments object');
});
QUnit.test('tail', function(assert) {
assert.strictEqual(_.tail, _.rest, 'is an alias for rest');
test('tail', function() {
strictEqual(_.rest, _.tail, 'alias for rest');
});
QUnit.test('drop', function(assert) {
assert.strictEqual(_.drop, _.rest, 'is an alias for rest');
test('drop', function() {
strictEqual(_.rest, _.drop, 'alias for rest');
});
QUnit.test('initial', function(assert) {
assert.deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'returns all but the last element');
assert.deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'returns all but the last n elements');
assert.deepEqual(_.initial([1, 2, 3, 4], 6), [], 'returns an empty array when n > length');
test('initial', function() {
deepEqual(_.initial([1, 2, 3, 4, 5]), [1, 2, 3, 4], 'working initial()');
deepEqual(_.initial([1, 2, 3, 4], 2), [1, 2], 'initial can take an index');
deepEqual(_.initial([1, 2, 3, 4], 6), [], 'initial can take a large index');
var result = (function(){ return _(arguments).initial(); }(1, 2, 3, 4));
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
deepEqual(result, [1, 2, 3], 'initial works on arguments object');
result = _.map([[1, 2, 3], [1, 2, 3]], _.initial);
assert.deepEqual(_.flatten(result), [1, 2, 1, 2], 'works well with _.map');
deepEqual(_.flatten(result), [1, 2, 1, 2], 'initial works with _.map');
});
QUnit.test('last', function(assert) {
assert.equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array');
assert.equal(_([1, 2, 3]).last(), 3, 'can perform OO-style "last()"');
assert.deepEqual(_.last([1, 2, 3], 0), [], 'returns an empty array when n <= 0 (0 case)');
assert.deepEqual(_.last([1, 2, 3], -1), [], 'returns an empty array when n <= 0 (negative case)');
assert.deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can fetch the last n elements');
assert.deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'returns the whole array if n > length');
test('last', function() {
equal(_.last([1, 2, 3]), 3, 'can pull out the last element of an array');
deepEqual(_.last([1, 2, 3], 0), [], 'can pass an index to last');
deepEqual(_.last([1, 2, 3], 2), [2, 3], 'can pass an index to last');
deepEqual(_.last([1, 2, 3], 5), [1, 2, 3], 'can pass an index to last');
var result = (function(){ return _(arguments).last(); }(1, 2, 3, 4));
assert.equal(result, 4, 'works on an arguments object');
equal(result, 4, 'works on an arguments object');
result = _.map([[1, 2, 3], [1, 2, 3]], _.last);
assert.deepEqual(result, [3, 3], 'works well with _.map');
assert.equal(_.last(null), void 0, 'returns undefined when called on null');
deepEqual(result, [3, 3], 'works well with _.map');
var arr = [];
arr[-1] = 'boo';
assert.equal(_.last(arr), void 0, 'return undefined when called on a empty array');
equal(_.last(null), undefined, 'handles nulls');
strictEqual(_.last([1, 2, 3], -1).length, 0);
});
QUnit.test('compact', function(assert) {
assert.deepEqual(_.compact([1, false, null, 0, '', void 0, NaN, 2]), [1, 2], 'removes all falsy values');
var result = (function(){ return _.compact(arguments); }(0, 1, false, 2, false, 3));
assert.deepEqual(result, [1, 2, 3], 'works on an arguments object');
result = _.map([[1, false, false], [false, false, 3]], _.compact);
assert.deepEqual(result, [[1], [3]], 'works well with _.map');
test('compact', function() {
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
var result = (function(){ return _.compact(arguments).length; }(0, 1, false, 2, false, 3));
equal(result, 3, 'works on an arguments object');
});
QUnit.test('flatten', function(assert) {
assert.deepEqual(_.flatten(null), [], 'supports null');
assert.deepEqual(_.flatten(void 0), [], 'supports undefined');
test('flatten', function() {
deepEqual(_.flatten(null), [], 'Flattens supports null');
deepEqual(_.flatten(void 0), [], 'Flattens supports undefined');
assert.deepEqual(_.flatten([[], [[]], []]), [], 'supports empty arrays');
assert.deepEqual(_.flatten([[], [[]], []], true), [[]], 'can shallowly flatten empty arrays');
deepEqual(_.flatten([[], [[]], []]), [], 'Flattens empty arrays');
deepEqual(_.flatten([[], [[]], []], true), [[]], 'Flattens empty arrays');
var list = [1, [2], [3, [[[4]]]]];
assert.deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays');
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays');
deepEqual(_.flatten(list), [1, 2, 3, 4], 'can flatten nested arrays');
deepEqual(_.flatten(list, true), [1, 2, 3, [[[4]]]], 'can shallowly flatten nested arrays');
var result = (function(){ return _.flatten(arguments); }(1, [2], [3, [[[4]]]]));
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
list = [[1], [2], [3], [[4]]];
assert.deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23, 'can flatten medium length arrays');
assert.equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23, 'can shallowly flatten medium length arrays');
assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'can handle massive arrays');
assert.equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'can handle massive arrays in shallow mode');
var x = _.range(100000);
for (var i = 0; i < 1000; i++) x = [x];
assert.deepEqual(_.flatten(x), _.range(100000), 'can handle very deep arrays');
assert.deepEqual(_.flatten(x, true), x[0], 'can handle very deep arrays in shallow mode');
equal(_.flatten([_.range(10), _.range(10), 5, 1, 3], true).length, 23);
equal(_.flatten([_.range(10), _.range(10), 5, 1, 3]).length, 23);
equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3]).length, 1056003, 'Flatten can handle massive collections');
equal(_.flatten([new Array(1000000), _.range(56000), 5, 1, 3], true).length, 1056003, 'Flatten can handle massive collections');
});
QUnit.test('without', function(assert) {
test('without', function() {
var list = [1, 2, 1, 0, 3, 1, 4];
assert.deepEqual(_.without(list, 0, 1), [2, 3, 4], 'removes all instances of the given values');
deepEqual(_.without(list, 0, 1), [2, 3, 4], 'can remove all instances of an object');
var result = (function(){ return _.without(arguments, 0, 1); }(1, 2, 1, 0, 3, 1, 4));
assert.deepEqual(result, [2, 3, 4], 'works on an arguments object');
deepEqual(result, [2, 3, 4], 'works on an arguments object');
list = [{one: 1}, {two: 2}];
assert.deepEqual(_.without(list, {one: 1}), list, 'compares objects by reference (value case)');
assert.deepEqual(_.without(list, list[0]), [{two: 2}], 'compares objects by reference (reference case)');
list = [{one : 1}, {two : 2}];
equal(_.without(list, {one : 1}).length, 2, 'uses real object identity for comparisons.');
equal(_.without(list, list[0]).length, 1, 'ditto.');
});
QUnit.test('sortedIndex', function(assert) {
var numbers = [10, 20, 30, 40, 50];
var indexFor35 = _.sortedIndex(numbers, 35);
assert.equal(indexFor35, 3, 'finds the index at which a value should be inserted to retain order');
test('sortedIndex', function() {
var numbers = [10, 20, 30, 40, 50], num = 35;
var indexForNum = _.sortedIndex(numbers, num);
equal(indexForNum, 3, '35 should be inserted at index 3');
var indexFor30 = _.sortedIndex(numbers, 30);
assert.equal(indexFor30, 2, 'finds the smallest index at which a value could be inserted to retain order');
equal(indexFor30, 2, '30 should be inserted at index 2');
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
var iterator = function(obj){ return obj.x; };
assert.strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2, 'uses the result of `iterator` for order comparisons');
assert.strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3, 'when `iterator` is a string, uses that key for order comparisons');
strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2);
strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3);
var context = {1: 2, 2: 3, 3: 4};
iterator = function(obj){ return this[obj]; };
assert.strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1, 'can execute its iterator in the given context');
strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1);
var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287,
1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647];
var largeArray = Array(Math.pow(2, 32) - 1);
var values = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215, 33554431, 67108863, 134217727, 268435455, 536870911, 1073741823, 2147483647];
var array = Array(Math.pow(2, 32) - 1);
var length = values.length;
// Sparsely populate `array`
while (length--) {
largeArray[values[length]] = values[length];
array[values[length]] = values[length];
}
assert.equal(_.sortedIndex(largeArray, 2147483648), 2147483648, 'works with large indexes');
equal(_.sortedIndex(array, 2147483648), 2147483648, 'should work with large indexes');
});
QUnit.test('uniq', function(assert) {
test('uniq', function() {
var list = [1, 2, 1, 3, 1, 4];
assert.deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array');
deepEqual(_.uniq(list), [1, 2, 3, 4], 'can find the unique values of an unsorted array');
list = [1, 1, 1, 2, 2, 3];
assert.deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster');
deepEqual(_.uniq(list, true), [1, 2, 3], 'can find the unique values of a sorted array faster');
list = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}, {name: 'Curly'}];
var expected = [{name: 'Moe'}, {name: 'Curly'}, {name: 'Larry'}];
var iterator = function(stooge) { return stooge.name; };
assert.deepEqual(_.uniq(list, false, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (unsorted case)');
assert.deepEqual(_.uniq(list, iterator), expected, '`sorted` argument defaults to false when omitted');
assert.deepEqual(_.uniq(list, 'name'), expected, 'when `iterator` is a string, uses that key for comparisons (unsorted case)');
list = [{name: 'moe'}, {name: 'curly'}, {name: 'larry'}, {name: 'curly'}];
var iterator = function(value) { return value.name; };
deepEqual(_.map(_.uniq(list, false, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator');
list = [{score: 8}, {score: 10}, {score: 10}];
expected = [{score: 8}, {score: 10}];
iterator = function(item) { return item.score; };
assert.deepEqual(_.uniq(list, true, iterator), expected, 'uses the result of `iterator` for uniqueness comparisons (sorted case)');
assert.deepEqual(_.uniq(list, true, 'score'), expected, 'when `iterator` is a string, uses that key for comparisons (sorted case)');
deepEqual(_.map(_.uniq(list, iterator), iterator), ['moe', 'curly', 'larry'], 'can find the unique values of an array using a custom iterator without specifying whether array is sorted');
iterator = function(value) { return value + 1; };
list = [1, 2, 2, 3, 4, 4];
deepEqual(_.uniq(list, true, iterator), [1, 2, 3, 4], 'iterator works with sorted array');
var kittens = [
{kitten: 'Celery', cuteness: 8},
{kitten: 'Juniper', cuteness: 10},
{kitten: 'Spottis', cuteness: 10}
];
var expected = [
{kitten: 'Celery', cuteness: 8},
{kitten: 'Juniper', cuteness: 10}
];
deepEqual(_.uniq(kittens, true, 'cuteness'), expected, 'string iterator works with sorted array');
assert.deepEqual(_.uniq([{0: 1}, {0: 1}, {0: 1}, {0: 2}], 0), [{0: 1}, {0: 2}], 'can use falsey pluck like iterator');
var result = (function(){ return _.uniq(arguments); }(1, 2, 1, 3, 1, 4));
assert.deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
deepEqual(result, [1, 2, 3, 4], 'works on an arguments object');
var a = {}, b = {}, c = {};
assert.deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered');
deepEqual(_.uniq([a, b, a, b, c]), [a, b, c], 'works on values that can be tested for equivalency but not ordered');
assert.deepEqual(_.uniq(null), [], 'returns an empty array when `array` is not iterable');
deepEqual(_.uniq(null), []);
var context = {};
list = [3];
_.uniq(list, function(value, index, array) {
assert.strictEqual(this, context, 'executes its iterator in the given context');
assert.strictEqual(value, 3, 'passes its iterator the value');
assert.strictEqual(index, 0, 'passes its iterator the index');
assert.strictEqual(array, list, 'passes its iterator the entire array');
strictEqual(this, context);
strictEqual(value, 3);
strictEqual(index, 0);
strictEqual(array, list);
}, context);
deepEqual(_.uniq([{a: 1, b: 1}, {a: 1, b: 2}, {a: 1, b: 3}, {a: 2, b: 1}], 'a'), [{a: 1, b: 1}, {a: 2, b: 1}], 'can use pluck like iterator');
deepEqual(_.uniq([{0: 1, b: 1}, {0: 1, b: 2}, {0: 1, b: 3}, {0: 2, b: 1}], 0), [{0: 1, b: 1}, {0: 2, b: 1}], 'can use falsey pluck like iterator');
});
QUnit.test('unique', function(assert) {
assert.strictEqual(_.unique, _.uniq, 'is an alias for uniq');
test('unique', function() {
strictEqual(_.uniq, _.unique, 'alias for uniq');
});
QUnit.test('intersection', function(assert) {
test('intersection', function() {
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
assert.deepEqual(_.intersection(stooges, leaders), ['moe'], 'can find the set intersection of two arrays');
assert.deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
deepEqual(_.intersection(stooges, leaders), ['moe'], 'can take the set intersection of two arrays');
deepEqual(_(stooges).intersection(leaders), ['moe'], 'can perform an OO-style intersection');
var result = (function(){ return _.intersection(arguments, leaders); }('moe', 'curly', 'larry'));
assert.deepEqual(result, ['moe'], 'works on an arguments object');
deepEqual(result, ['moe'], 'works on an arguments object');
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
assert.deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
deepEqual(_.intersection(theSixStooges, leaders), ['moe'], 'returns a duplicate-free array');
result = _.intersection([2, 4, 3, 1], [1, 2, 3]);
assert.deepEqual(result, [2, 3, 1], 'preserves the order of the first array');
deepEqual(result, [2, 3, 1], 'preserves order of first array');
result = _.intersection(null, [1, 2, 3]);
assert.deepEqual(result, [], 'returns an empty array when passed null as the first argument');
equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as first argument');
equal(result.length, 0, 'returns an empty array when passed null as first argument');
result = _.intersection([1, 2, 3], null);
assert.deepEqual(result, [], 'returns an empty array when passed null as an argument beyond the first');
equal(Object.prototype.toString.call(result), '[object Array]', 'returns an empty array when passed null as argument beyond the first');
equal(result.length, 0, 'returns an empty array when passed null as argument beyond the first');
});
QUnit.test('union', function(assert) {
test('union', function() {
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can find the union of a list of arrays');
result = _([1, 2, 3]).union([2, 30, 1], [1, 40]);
assert.deepEqual(result, [1, 2, 3, 30, 40], 'can perform an OO-style union');
deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
assert.deepEqual(result, [1, 2, 3, 30, 40, [1]], 'can find the union of a list of nested arrays');
deepEqual(result, [1, 2, 3, 30, 40, [1]], 'takes the union of a list of nested arrays');
result = _.union([10, 20], [1, 30, 10], [0, 40]);
assert.deepEqual(result, [10, 20, 1, 30, 0, 40], 'orders values by their first encounter');
var args = null;
(function(){ args = arguments; }(1, 2, 3));
result = _.union(args, [2, 30, 1], [1, 40]);
deepEqual(result, [1, 2, 3, 30, 40], 'takes the union of a list of arrays');
result = (function(){ return _.union(arguments, [2, 30, 1], [1, 40]); }(1, 2, 3));
assert.deepEqual(result, [1, 2, 3, 30, 40], 'works on an arguments object');
assert.deepEqual(_.union([1, 2, 3], 4), [1, 2, 3], 'restricts the union to arrays only');
result = _.union([1, 2, 3], 4);
deepEqual(result, [1, 2, 3], 'restrict the union to arrays only');
});
QUnit.test('difference', function(assert) {
test('difference', function() {
var result = _.difference([1, 2, 3], [2, 30, 40]);
assert.deepEqual(result, [1, 3], 'can find the difference of two arrays');
result = _([1, 2, 3]).difference([2, 30, 40]);
assert.deepEqual(result, [1, 3], 'can perform an OO-style difference');
deepEqual(result, [1, 3], 'takes the difference of two arrays');
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
assert.deepEqual(result, [3, 4], 'can find the difference of three arrays');
result = _.difference([8, 9, 3, 1], [3, 8]);
assert.deepEqual(result, [9, 1], 'preserves the order of the first array');
result = (function(){ return _.difference(arguments, [2, 30, 40]); }(1, 2, 3));
assert.deepEqual(result, [1, 3], 'works on an arguments object');
deepEqual(result, [3, 4], 'takes the difference of three arrays');
result = _.difference([1, 2, 3], 1);
assert.deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
deepEqual(result, [1, 2, 3], 'restrict the difference to arrays only');
});
QUnit.test('zip', function(assert) {
test('zip', function() {
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
assert.deepEqual(_.zip(names, ages, leaders), [
deepEqual(_.zip(names, ages, leaders), [
['moe', 30, true],
['larry', 40, void 0],
['curly', 50, void 0]
['larry', 40, undefined],
['curly', 50, undefined]
], 'zipped together arrays of different lengths');
var stooges = _.zip(['moe', 30, 'stooge 1'], ['larry', 40, 'stooge 2'], ['curly', 50, 'stooge 3']);
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
// In the case of different lengths of the tuples, undefined values
// In the case of difference lengths of the tuples undefineds
// should be used as placeholder
stooges = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
assert.deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [void 0, void 0, 'extra data']], 'zipped pairs with empties');
deepEqual(stooges, [['moe', 'larry', 'curly'], [30, 40, 50], [undefined, undefined, 'extra data']], 'zipped pairs with empties');
var empty = _.zip([]);
assert.deepEqual(empty, [], 'unzipped empty');
deepEqual(empty, [], 'unzipped empty');
assert.deepEqual(_.zip(null), [], 'handles null');
assert.deepEqual(_.zip(), [], '_.zip() returns []');
deepEqual(_.zip(null), [], 'handles null');
deepEqual(_.zip(), [], '_.zip() returns []');
});
QUnit.test('unzip', function(assert) {
assert.deepEqual(_.unzip(null), [], 'handles null');
test('unzip', function() {
deepEqual(_.unzip(null), [], 'handles null');
assert.deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]);
deepEqual(_.unzip([['a', 'b'], [1, 2]]), [['a', 1], ['b', 2]]);
// complements zip
var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
assert.deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]);
deepEqual(_.unzip(zipped), [['fred', 'barney'], [30, 40], [true, false]]);
zipped = _.zip(['moe', 30], ['larry', 40], ['curly', 50, 'extra data']);
assert.deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array');
deepEqual(_.unzip(zipped), [['moe', 30, void 0], ['larry', 40, void 0], ['curly', 50, 'extra data']], 'Uses length of largest array');
});
QUnit.test('object', function(assert) {
test('object', function() {
var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
var shouldBe = {moe: 30, larry: 40, curly: 50};
assert.deepEqual(result, shouldBe, 'two arrays zipped together into an object');
deepEqual(result, shouldBe, 'two arrays zipped together into an object');
result = _.object([['one', 1], ['two', 2], ['three', 3]]);
shouldBe = {one: 1, two: 2, three: 3};
assert.deepEqual(result, shouldBe, 'an array of pairs zipped together into an object');
deepEqual(result, shouldBe, 'an array of pairs zipped together into an object');
var stooges = {moe: 30, larry: 40, curly: 50};
assert.deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object');
deepEqual(_.object(_.pairs(stooges)), stooges, 'an object converted to pairs and back to an object');
assert.deepEqual(_.object(null), {}, 'handles nulls');
deepEqual(_.object(null), {}, 'handles nulls');
});
QUnit.test('indexOf', function(assert) {
test('indexOf', function() {
var numbers = [1, 2, 3];
assert.equal(_.indexOf(numbers, 2), 1, 'can compute indexOf');
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf');
var result = (function(){ return _.indexOf(arguments, 2); }(1, 2, 3));
assert.equal(result, 1, 'works on an arguments object');
equal(result, 1, 'works on an arguments object');
_.each([null, void 0, [], false], function(val) {
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
assert.equal(_.indexOf(val, 2), -1, msg);
assert.equal(_.indexOf(val, 2, -1), -1, msg);
assert.equal(_.indexOf(val, 2, -20), -1, msg);
assert.equal(_.indexOf(val, 2, 15), -1, msg);
equal(_.indexOf(val, 2), -1, msg);
equal(_.indexOf(val, 2, -1), -1, msg);
equal(_.indexOf(val, 2, -20), -1, msg);
equal(_.indexOf(val, 2, 15), -1, msg);
});
var num = 35;
numbers = [10, 20, 30, 40, 50];
var index = _.indexOf(numbers, num, true);
assert.equal(index, -1, '35 is not in the list');
equal(index, -1, '35 is not in the list');
numbers = [10, 20, 30, 40, 50]; num = 40;
index = _.indexOf(numbers, num, true);
assert.equal(index, 3, '40 is in the list');
equal(index, 3, '40 is in the list');
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
assert.equal(_.indexOf(numbers, num, true), 1, '40 is in the list');
assert.equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list');
assert.equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search');
assert.ok(_.every(['1', [], {}, null], function() {
equal(_.indexOf(numbers, num, true), 1, '40 is in the list');
equal(_.indexOf(numbers, 6, true), -1, '6 isnt in the list');
equal(_.indexOf([1, 2, 5, 4, 6, 7], 5, true), -1, 'sorted indexOf doesn\'t uses binary search');
ok(_.every(['1', [], {}, null], function() {
return _.indexOf(numbers, num, {}) === 1;
}), 'non-nums as fromIndex make indexOf assume sorted');
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
index = _.indexOf(numbers, 2, 5);
assert.equal(index, 7, 'supports the fromIndex argument');
equal(index, 7, 'supports the fromIndex argument');
index = _.indexOf([,,, 0], void 0);
assert.equal(index, 0, 'treats sparse arrays as if they were dense');
index = _.indexOf([,,,], undefined);
equal(index, 0, 'treats sparse arrays as if they were dense');
var array = [1, 2, 3, 1, 2, 3];
assert.strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
assert.strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index');
assert.strictEqual(_.indexOf(array, 2, -3), 4);
strictEqual(_.indexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
strictEqual(_.indexOf(array, 1, -2), -1, 'neg `fromIndex` starts at the right index');
strictEqual(_.indexOf(array, 2, -3), 4);
_.each([-6, -8, -Infinity], function(fromIndex) {
assert.strictEqual(_.indexOf(array, 1, fromIndex), 0);
strictEqual(_.indexOf(array, 1, fromIndex), 0);
});
assert.strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
strictEqual(_.indexOf([1, 2, 3], 1, true), 0);
index = _.indexOf([], void 0, true);
assert.equal(index, -1, 'empty array with truthy `isSorted` returns -1');
index = _.indexOf([], undefined, true);
equal(index, -1, 'empty array with truthy `isSorted` returns -1');
});
QUnit.test('indexOf with NaN', function(assert) {
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN');
assert.strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
test('indexOf with NaN', function() {
strictEqual(_.indexOf([1, 2, NaN, NaN], NaN), 2, 'Expected [1, 2, NaN] to contain NaN');
strictEqual(_.indexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result');
assert.strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result');
strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, 1), 2, 'startIndex does not affect result');
strictEqual(_.indexOf([1, 2, NaN, NaN], NaN, -2), 2, 'startIndex does not affect result');
(function() {
assert.strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN');
strictEqual(_.indexOf(arguments, NaN), 2, 'Expected arguments [1, 2, NaN] to contain NaN');
}(1, 2, NaN, NaN));
});
QUnit.test('indexOf with +- 0', function(assert) {
test('indexOf with +- 0', function() {
_.each([-0, +0], function(val) {
assert.strictEqual(_.indexOf([1, 2, val, val], val), 2);
assert.strictEqual(_.indexOf([1, 2, val, val], -val), 2);
strictEqual(_.indexOf([1, 2, val, val], val), 2);
strictEqual(_.indexOf([1, 2, val, val], -val), 2);
});
});
QUnit.test('lastIndexOf', function(assert) {
test('lastIndexOf', function() {
var numbers = [1, 0, 1];
var falsey = [void 0, '', 0, false, NaN, null, void 0];
assert.equal(_.lastIndexOf(numbers, 1), 2);
var falsey = [void 0, '', 0, false, NaN, null, undefined];
equal(_.lastIndexOf(numbers, 1), 2);
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
numbers.lastIndexOf = null;
assert.equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
assert.equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
var result = (function(){ return _.lastIndexOf(arguments, 1); }(1, 0, 1, 0, 0, 1, 0, 0, 0));
assert.equal(result, 5, 'works on an arguments object');
equal(result, 5, 'works on an arguments object');
_.each([null, void 0, [], false], function(val) {
var msg = 'Handles: ' + (_.isArray(val) ? '[]' : val);
assert.equal(_.lastIndexOf(val, 2), -1, msg);
assert.equal(_.lastIndexOf(val, 2, -1), -1, msg);
assert.equal(_.lastIndexOf(val, 2, -20), -1, msg);
assert.equal(_.lastIndexOf(val, 2, 15), -1, msg);
equal(_.lastIndexOf(val, 2), -1, msg);
equal(_.lastIndexOf(val, 2, -1), -1, msg);
equal(_.lastIndexOf(val, 2, -20), -1, msg);
equal(_.lastIndexOf(val, 2, 15), -1, msg);
});
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
var index = _.lastIndexOf(numbers, 2, 2);
assert.equal(index, 1, 'supports the fromIndex argument');
equal(index, 1, 'supports the fromIndex argument');
var array = [1, 2, 3, 1, 2, 3];
assert.strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx');
assert.strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value');
assert.strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value');
strictEqual(_.lastIndexOf(array, 1, 0), 0, 'starts at the correct from idx');
strictEqual(_.lastIndexOf(array, 3), 5, 'should return the index of the last matched value');
strictEqual(_.lastIndexOf(array, 4), -1, 'should return `-1` for an unmatched value');
assert.strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`');
strictEqual(_.lastIndexOf(array, 1, 2), 0, 'should work with a positive `fromIndex`');
_.each([6, 8, Math.pow(2, 32), Infinity], function(fromIndex) {
assert.strictEqual(_.lastIndexOf(array, void 0, fromIndex), -1);
assert.strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
assert.strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
strictEqual(_.lastIndexOf(array, undefined, fromIndex), -1);
strictEqual(_.lastIndexOf(array, 1, fromIndex), 3);
strictEqual(_.lastIndexOf(array, '', fromIndex), -1);
});
var expected = _.map(falsey, function(value) {
@@ -414,150 +405,133 @@
return _.lastIndexOf(array, 3, fromIndex);
});
assert.deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`');
assert.strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`');
assert.strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`');
deepEqual(actual, expected, 'should treat falsey `fromIndex` values, except `0` and `NaN`, as `array.length`');
strictEqual(_.lastIndexOf(array, 3, '1'), 5, 'should treat non-number `fromIndex` values as `array.length`');
strictEqual(_.lastIndexOf(array, 3, true), 5, 'should treat non-number `fromIndex` values as `array.length`');
assert.strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`');
assert.strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
strictEqual(_.lastIndexOf(array, 2, -3), 1, 'should work with a negative `fromIndex`');
strictEqual(_.lastIndexOf(array, 1, -3), 3, 'neg `fromIndex` starts at the right index');
assert.deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) {
deepEqual(_.map([-6, -8, -Infinity], function(fromIndex) {
return _.lastIndexOf(array, 1, fromIndex);
}), [0, -1, -1]);
});
QUnit.test('lastIndexOf with NaN', function(assert) {
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
assert.strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
test('lastIndexOf with NaN', function() {
strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN), 3, 'Expected [1, 2, NaN] to contain NaN');
strictEqual(_.lastIndexOf([1, 2, Infinity], NaN), -1, 'Expected [1, 2, NaN] to contain NaN');
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
assert.strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, 2), 2, 'fromIndex does not affect result');
strictEqual(_.lastIndexOf([1, 2, NaN, NaN], NaN, -2), 2, 'fromIndex does not affect result');
(function() {
assert.strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN');
strictEqual(_.lastIndexOf(arguments, NaN), 3, 'Expected arguments [1, 2, NaN] to contain NaN');
}(1, 2, NaN, NaN));
});
QUnit.test('lastIndexOf with +- 0', function(assert) {
test('lastIndexOf with +- 0', function() {
_.each([-0, +0], function(val) {
assert.strictEqual(_.lastIndexOf([1, 2, val, val], val), 3);
assert.strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3);
assert.strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1);
strictEqual(_.lastIndexOf([1, 2, val, val], val), 3);
strictEqual(_.lastIndexOf([1, 2, val, val], -val), 3);
strictEqual(_.lastIndexOf([-1, 1, 2], -val), -1);
});
});
QUnit.test('findIndex', function(assert) {
test('findIndex', function() {
var objects = [
{a: 0, b: 0},
{a: 1, b: 1},
{a: 2, b: 2},
{a: 0, b: 0}
{'a': 0, 'b': 0},
{'a': 1, 'b': 1},
{'a': 2, 'b': 2},
{'a': 0, 'b': 0}
];
assert.equal(_.findIndex(objects, function(obj) {
equal(_.findIndex(objects, function(obj) {
return obj.a === 0;
}), 0);
assert.equal(_.findIndex(objects, function(obj) {
equal(_.findIndex(objects, function(obj) {
return obj.b * obj.a === 4;
}), 2);
assert.equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator');
equal(_.findIndex(objects, 'a'), 1, 'Uses lookupIterator');
assert.equal(_.findIndex(objects, function(obj) {
equal(_.findIndex(objects, function(obj) {
return obj.b * obj.a === 5;
}), -1);
assert.equal(_.findIndex(null, _.noop), -1);
assert.strictEqual(_.findIndex(objects, function(a) {
equal(_.findIndex(null, _.noop), -1);
strictEqual(_.findIndex(objects, function(a) {
return a.foo === null;
}), -1);
_.findIndex([{a: 1}], function(a, key, obj) {
assert.equal(key, 0);
assert.deepEqual(obj, [{a: 1}]);
assert.strictEqual(this, objects, 'called with context');
equal(key, 0);
deepEqual(obj, [{a: 1}]);
strictEqual(this, objects, 'called with context');
}, objects);
var sparse = [];
sparse[20] = {a: 2, b: 2};
assert.equal(_.findIndex(sparse, function(obj) {
sparse[20] = {'a': 2, 'b': 2};
equal(_.findIndex(sparse, function(obj) {
return obj && obj.b * obj.a === 4;
}), 20, 'Works with sparse arrays');
var array = [1, 2, 3, 4];
array.match = 55;
assert.strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
strictEqual(_.findIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
});
QUnit.test('findLastIndex', function(assert) {
test('findLastIndex', function() {
var objects = [
{a: 0, b: 0},
{a: 1, b: 1},
{a: 2, b: 2},
{a: 0, b: 0}
{'a': 0, 'b': 0},
{'a': 1, 'b': 1},
{'a': 2, 'b': 2},
{'a': 0, 'b': 0}
];
assert.equal(_.findLastIndex(objects, function(obj) {
equal(_.findLastIndex(objects, function(obj) {
return obj.a === 0;
}), 3);
assert.equal(_.findLastIndex(objects, function(obj) {
equal(_.findLastIndex(objects, function(obj) {
return obj.b * obj.a === 4;
}), 2);
assert.equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator');
equal(_.findLastIndex(objects, 'a'), 2, 'Uses lookupIterator');
assert.equal(_.findLastIndex(objects, function(obj) {
equal(_.findLastIndex(objects, function(obj) {
return obj.b * obj.a === 5;
}), -1);
assert.equal(_.findLastIndex(null, _.noop), -1);
assert.strictEqual(_.findLastIndex(objects, function(a) {
equal(_.findLastIndex(null, _.noop), -1);
strictEqual(_.findLastIndex(objects, function(a) {
return a.foo === null;
}), -1);
_.findLastIndex([{a: 1}], function(a, key, obj) {
assert.equal(key, 0);
assert.deepEqual(obj, [{a: 1}]);
assert.strictEqual(this, objects, 'called with context');
equal(key, 0);
deepEqual(obj, [{a: 1}]);
strictEqual(this, objects, 'called with context');
}, objects);
var sparse = [];
sparse[20] = {a: 2, b: 2};
assert.equal(_.findLastIndex(sparse, function(obj) {
sparse[20] = {'a': 2, 'b': 2};
equal(_.findLastIndex(sparse, function(obj) {
return obj && obj.b * obj.a === 4;
}), 20, 'Works with sparse arrays');
var array = [1, 2, 3, 4];
array.match = 55;
assert.strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
strictEqual(_.findLastIndex(array, function(x) { return x === 55; }), -1, 'doesn\'t match array-likes keys');
});
QUnit.test('range', function(assert) {
assert.deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array');
assert.deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
assert.deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a &amp; b, a&lt;b generates an array of elements a,a+1,a+2,...,b-2,b-1');
assert.deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a &amp; b &amp; c, c &lt; b-a, a &lt; b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) &lt; c');
assert.deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a &amp; b &amp; c, c &gt; b-a, a &lt; b generates an array with a single element, equal to a');
assert.deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a &amp; b &amp; c, a &gt; b, c &lt; 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
assert.deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs');
assert.strictEqual(1 / _.range(-0, 1)[0], -Infinity, 'should preserve -0');
assert.deepEqual(_.range(8, 5), [8, 7, 6], 'negative range generates descending array');
assert.deepEqual(_.range(-3), [0, -1, -2], 'negative range generates descending array');
test('range', function() {
deepEqual(_.range(0), [], 'range with 0 as a first argument generates an empty array');
deepEqual(_.range(4), [0, 1, 2, 3], 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
deepEqual(_.range(5, 8), [5, 6, 7], 'range with two arguments a &amp; b, a&lt;b generates an array of elements a,a+1,a+2,...,b-2,b-1');
deepEqual(_.range(8, 5), [], 'range with two arguments a &amp; b, b&lt;a generates an empty array');
deepEqual(_.range(3, 10, 3), [3, 6, 9], 'range with three arguments a &amp; b &amp; c, c &lt; b-a, a &lt; b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) &lt; c');
deepEqual(_.range(3, 10, 15), [3], 'range with three arguments a &amp; b &amp; c, c &gt; b-a, a &lt; b generates an array with a single element, equal to a');
deepEqual(_.range(12, 7, -2), [12, 10, 8], 'range with three arguments a &amp; b &amp; c, a &gt; b, c &lt; 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
deepEqual(_.range(0, -10, -1), [0, -1, -2, -3, -4, -5, -6, -7, -8, -9], 'final example in the Python docs');
});
QUnit.test('chunk', function(assert) {
assert.deepEqual(_.chunk([], 2), [], 'chunk for empty array returns an empty array');
assert.deepEqual(_.chunk([1, 2, 3], 0), [], 'chunk into parts of 0 elements returns empty array');
assert.deepEqual(_.chunk([1, 2, 3], -1), [], 'chunk into parts of negative amount of elements returns an empty array');
assert.deepEqual(_.chunk([1, 2, 3]), [], 'defaults to empty array (chunk size 0)');
assert.deepEqual(_.chunk([1, 2, 3], 1), [[1], [2], [3]], 'chunk into parts of 1 elements returns original array');
assert.deepEqual(_.chunk([1, 2, 3], 3), [[1, 2, 3]], 'chunk into parts of current array length elements returns the original array');
assert.deepEqual(_.chunk([1, 2, 3], 5), [[1, 2, 3]], 'chunk into parts of more then current array length elements returns the original array');
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 2), [[10, 20], [30, 40], [50, 60], [70]], 'chunk into parts of less then current array length elements');
assert.deepEqual(_.chunk([10, 20, 30, 40, 50, 60, 70], 3), [[10, 20, 30], [40, 50, 60], [70]], 'chunk into parts of less then current array length elements');
});
}());

View File

@@ -3,7 +3,7 @@
QUnit.module('Chaining');
QUnit.test('map/flatten/reduce', function(assert) {
test('map/flatten/reduce', function() {
var lyrics = [
'I\'m a lumberjack and I\'m okay',
'I sleep all night and I work all day',
@@ -17,13 +17,12 @@
hash[l] = hash[l] || 0;
hash[l]++;
return hash;
}, {})
.value();
assert.equal(counts.a, 16, 'counted all the letters in the song');
assert.equal(counts.e, 10, 'counted all the letters in the song');
}, {}).value();
equal(counts.a, 16, 'counted all the letters in the song');
equal(counts.e, 10, 'counted all the letters in the song');
});
QUnit.test('select/reject/sortBy', function(assert) {
test('select/reject/sortBy', function() {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
numbers = _(numbers).chain().select(function(n) {
return n % 2 === 0;
@@ -32,10 +31,10 @@
}).sortBy(function(n) {
return -n;
}).value();
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
});
QUnit.test('select/reject/sortBy in functional style', function(assert) {
test('select/reject/sortBy in functional style', function() {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
numbers = _.chain(numbers).select(function(n) {
return n % 2 === 0;
@@ -44,10 +43,10 @@
}).sortBy(function(n) {
return -n;
}).value();
assert.deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers');
});
QUnit.test('reverse/concat/unshift/pop/map', function(assert) {
test('reverse/concat/unshift/pop/map', function() {
var numbers = [1, 2, 3, 4, 5];
numbers = _(numbers).chain()
.reverse()
@@ -56,44 +55,44 @@
.pop()
.map(function(n){ return n * 2; })
.value();
assert.deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.');
deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.');
});
QUnit.test('splice', function(assert) {
test('splice', function() {
var instance = _([1, 2, 3, 4, 5]).chain();
assert.deepEqual(instance.splice(1, 3).value(), [1, 5]);
assert.deepEqual(instance.splice(1, 0).value(), [1, 5]);
assert.deepEqual(instance.splice(1, 1).value(), [1]);
assert.deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array');
deepEqual(instance.splice(1, 3).value(), [1, 5]);
deepEqual(instance.splice(1, 0).value(), [1, 5]);
deepEqual(instance.splice(1, 1).value(), [1]);
deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array');
});
QUnit.test('shift', function(assert) {
test('shift', function() {
var instance = _([1, 2, 3]).chain();
assert.deepEqual(instance.shift().value(), [2, 3]);
assert.deepEqual(instance.shift().value(), [3]);
assert.deepEqual(instance.shift().value(), [], '#397 Can create empty array');
deepEqual(instance.shift().value(), [2, 3]);
deepEqual(instance.shift().value(), [3]);
deepEqual(instance.shift().value(), [], '#397 Can create empty array');
});
QUnit.test('pop', function(assert) {
test('pop', function() {
var instance = _([1, 2, 3]).chain();
assert.deepEqual(instance.pop().value(), [1, 2]);
assert.deepEqual(instance.pop().value(), [1]);
assert.deepEqual(instance.pop().value(), [], '#397 Can create empty array');
deepEqual(instance.pop().value(), [1, 2]);
deepEqual(instance.pop().value(), [1]);
deepEqual(instance.pop().value(), [], '#397 Can create empty array');
});
QUnit.test('chaining works in small stages', function(assert) {
test('chaining works in small stages', function() {
var o = _([1, 2, 3, 4]).chain();
assert.deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
assert.deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
});
QUnit.test('#1562: Engine proxies for chained functions', function(assert) {
test('#1562: Engine proxies for chained functions', function() {
var wrapped = _(512);
assert.strictEqual(wrapped.toJSON(), 512);
assert.strictEqual(wrapped.valueOf(), 512);
assert.strictEqual(+wrapped, 512);
assert.strictEqual(wrapped.toString(), '512');
assert.strictEqual('' + wrapped, '512');
strictEqual(wrapped.toJSON(), 512);
strictEqual(wrapped.valueOf(), 512);
strictEqual(+wrapped, 512);
strictEqual(wrapped.toString(), '512');
strictEqual('' + wrapped, '512');
});
}());

File diff suppressed because it is too large Load Diff

View File

@@ -33,95 +33,95 @@
);
iDoc.close();
QUnit.test('isEqual', function(assert) {
test('isEqual', function() {
assert.notOk(_.isEqual(iNumber, 101));
assert.ok(_.isEqual(iNumber, 100));
ok(!_.isEqual(iNumber, 101));
ok(_.isEqual(iNumber, 100));
// Objects from another frame.
assert.ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal');
ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal');
// Array from another frame.
assert.ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal');
ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal');
});
QUnit.test('isEmpty', function(assert) {
assert.notOk(_([iNumber]).isEmpty(), '[1] is not empty');
assert.notOk(_.isEmpty(iArray), '[] is empty');
assert.ok(_.isEmpty(iObject), '{} is empty');
test('isEmpty', function() {
ok(!_([iNumber]).isEmpty(), '[1] is not empty');
ok(!_.isEmpty(iArray), '[] is empty');
ok(_.isEmpty(iObject), '{} is empty');
});
QUnit.test('isElement', function(assert) {
assert.notOk(_.isElement('div'), 'strings are not dom elements');
assert.ok(_.isElement(document.body), 'the body tag is a DOM element');
assert.ok(_.isElement(iElement), 'even from another frame');
test('isElement', function() {
ok(!_.isElement('div'), 'strings are not dom elements');
ok(_.isElement(document.body), 'the body tag is a DOM element');
ok(_.isElement(iElement), 'even from another frame');
});
QUnit.test('isArguments', function(assert) {
assert.ok(_.isArguments(iArguments), 'even from another frame');
test('isArguments', function() {
ok(_.isArguments(iArguments), 'even from another frame');
});
QUnit.test('isObject', function(assert) {
assert.ok(_.isObject(iElement), 'even from another frame');
assert.ok(_.isObject(iFunction), 'even from another frame');
test('isObject', function() {
ok(_.isObject(iElement), 'even from another frame');
ok(_.isObject(iFunction), 'even from another frame');
});
QUnit.test('isArray', function(assert) {
assert.ok(_.isArray(iArray), 'even from another frame');
test('isArray', function() {
ok(_.isArray(iArray), 'even from another frame');
});
QUnit.test('isString', function(assert) {
assert.ok(_.isString(iString), 'even from another frame');
test('isString', function() {
ok(_.isString(iString), 'even from another frame');
});
QUnit.test('isNumber', function(assert) {
assert.ok(_.isNumber(iNumber), 'even from another frame');
test('isNumber', function() {
ok(_.isNumber(iNumber), 'even from another frame');
});
QUnit.test('isBoolean', function(assert) {
assert.ok(_.isBoolean(iBoolean), 'even from another frame');
test('isBoolean', function() {
ok(_.isBoolean(iBoolean), 'even from another frame');
});
QUnit.test('isFunction', function(assert) {
assert.ok(_.isFunction(iFunction), 'even from another frame');
test('isFunction', function() {
ok(_.isFunction(iFunction), 'even from another frame');
});
QUnit.test('isDate', function(assert) {
assert.ok(_.isDate(iDate), 'even from another frame');
test('isDate', function() {
ok(_.isDate(iDate), 'even from another frame');
});
QUnit.test('isRegExp', function(assert) {
assert.ok(_.isRegExp(iRegExp), 'even from another frame');
test('isRegExp', function() {
ok(_.isRegExp(iRegExp), 'even from another frame');
});
QUnit.test('isNaN', function(assert) {
assert.ok(_.isNaN(iNaN), 'even from another frame');
test('isNaN', function() {
ok(_.isNaN(iNaN), 'even from another frame');
});
QUnit.test('isNull', function(assert) {
assert.ok(_.isNull(iNull), 'even from another frame');
test('isNull', function() {
ok(_.isNull(iNull), 'even from another frame');
});
QUnit.test('isUndefined', function(assert) {
assert.ok(_.isUndefined(iUndefined), 'even from another frame');
test('isUndefined', function() {
ok(_.isUndefined(iUndefined), 'even from another frame');
});
QUnit.test('isError', function(assert) {
assert.ok(_.isError(iError), 'even from another frame');
test('isError', function() {
ok(_.isError(iError), 'even from another frame');
});
if (typeof ActiveXObject != 'undefined') {
QUnit.test('IE host objects', function(assert) {
test('IE host objects', function() {
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
assert.notOk(_.isNumber(xml));
assert.notOk(_.isBoolean(xml));
assert.notOk(_.isNaN(xml));
assert.notOk(_.isFunction(xml));
assert.notOk(_.isNull(xml));
assert.notOk(_.isUndefined(xml));
ok(!_.isNumber(xml));
ok(!_.isBoolean(xml));
ok(!_.isNaN(xml));
ok(!_.isFunction(xml));
ok(!_.isNull(xml));
ok(!_.isUndefined(xml));
});
QUnit.test('#1621 IE 11 compat mode DOM elements are not functions', function(assert) {
test('#1621 IE 11 compat mode DOM elements are not functions', function() {
var fn = function() {};
var xml = new ActiveXObject('Msxml2.DOMDocument.3.0');
var div = document.createElement('div');
@@ -132,10 +132,10 @@
_.isFunction(fn);
}
assert.equal(_.isFunction(xml), false);
assert.equal(_.isFunction(div), false);
assert.equal(_.isFunction(fn), true);
equal(_.isFunction(xml), false);
equal(_.isFunction(div), false);
equal(_.isFunction(fn), true);
});
}
}());
}());

View File

@@ -4,65 +4,65 @@
QUnit.module('Functions');
QUnit.config.asyncRetries = 3;
QUnit.test('bind', function(assert) {
var context = {name: 'moe'};
test('bind', function() {
var context = {name : 'moe'};
var func = function(arg) { return 'name: ' + (this.name || arg); };
var bound = _.bind(func, context);
assert.equal(bound(), 'name: moe', 'can bind a function to a context');
equal(bound(), 'name: moe', 'can bind a function to a context');
bound = _(func).bind(context);
assert.equal(bound(), 'name: moe', 'can do OO-style binding');
equal(bound(), 'name: moe', 'can do OO-style binding');
bound = _.bind(func, null, 'curly');
var result = bound();
// Work around a PhantomJS bug when applying a function with null|undefined.
assert.ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context');
ok(result === 'name: curly' || result === 'name: ' + window.name, 'can bind without specifying a context');
func = function(salutation, name) { return salutation + ': ' + name; };
func = _.bind(func, this, 'hello');
assert.equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
func = _.bind(func, this, 'curly');
assert.equal(func(), 'hello: curly', 'the function was completely applied in advance');
equal(func(), 'hello: curly', 'the function was completely applied in advance');
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
func = _.bind(func, this, 'hello', 'moe', 'curly');
assert.equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
func = function(ctx, message) { assert.equal(this, ctx, message); };
func = function(context, message) { equal(this, context, message); };
_.bind(func, 0, 0, 'can bind a function to `0`')();
_.bind(func, '', '', 'can bind a function to an empty string')();
_.bind(func, false, false, 'can bind a function to `false`')();
// These tests are only meaningful when using a browser without a native bind function
// To test this with a modern browser, set underscore's nativeBind to undefined
var F = function() { return this; };
var F = function () { return this; };
var boundf = _.bind(F, {hello: 'moe curly'});
var Boundf = boundf; // make eslint happy.
var newBoundf = new Boundf();
assert.equal(newBoundf.hello, void 0, 'function should not be bound to the context, to comply with ECMAScript 5');
assert.equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context");
assert.ok(newBoundf instanceof F, 'a bound instance is an instance of the original function');
equal(newBoundf.hello, undefined, 'function should not be bound to the context, to comply with ECMAScript 5');
equal(boundf().hello, 'moe curly', "When called without the new operator, it's OK to be bound to the context");
ok(newBoundf instanceof F, 'a bound instance is an instance of the original function');
assert.raises(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function');
throws(function() { _.bind('notafunction'); }, TypeError, 'throws an error when binding to a non-function');
});
QUnit.test('partial', function(assert) {
test('partial', function() {
var obj = {name: 'moe'};
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
obj.func = _.partial(func, 'a', 'b');
assert.equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
obj.func = _.partial(func, _, 'b', _, 'd');
assert.equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders');
equal(obj.func('a', 'c'), 'moe a b c d', 'can partially apply with placeholders');
func = _.partial(function() { return arguments.length; }, _, 'b', _, 'd');
assert.equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders');
assert.equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders');
equal(func('a', 'c', 'e'), 5, 'accepts more arguments than the number of placeholders');
equal(func('a'), 4, 'accepts fewer arguments than the number of placeholders');
func = _.partial(function() { return typeof arguments[2]; }, _, 'b', _, 'd');
assert.equal(func('a'), 'undefined', 'unfilled placeholders are undefined');
equal(func('a'), 'undefined', 'unfilled placeholders are undefined');
// passes context
function MyWidget(name, options) {
@@ -74,93 +74,78 @@
};
var MyWidgetWithCoolOpts = _.partial(MyWidget, _, {a: 1});
var widget = new MyWidgetWithCoolOpts('foo');
assert.ok(widget instanceof MyWidget, 'Can partially bind a constructor');
assert.equal(widget.get(), 'foo', 'keeps prototype');
assert.deepEqual(widget.options, {a: 1});
_.partial.placeholder = obj;
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
assert.equal(func('a'), 4, 'allows the placeholder to be swapped out');
_.partial.placeholder = {};
func = _.partial(function() { return arguments.length; }, obj, 'b', obj, 'd');
assert.equal(func('a'), 5, 'swapping the placeholder preserves previously bound arguments');
_.partial.placeholder = _;
ok(widget instanceof MyWidget, 'Can partially bind a constructor');
equal(widget.get(), 'foo', 'keeps prototype');
deepEqual(widget.options, {a: 1});
});
QUnit.test('bindAll', function(assert) {
var curly = {name: 'curly'};
var moe = {
name: 'moe',
getName: function() { return 'name: ' + this.name; },
sayHi: function() { return 'hi: ' + this.name; }
test('bindAll', function() {
var curly = {name : 'curly'}, moe = {
name : 'moe',
getName : function() { return 'name: ' + this.name; },
sayHi : function() { return 'hi: ' + this.name; }
};
curly.getName = moe.getName;
_.bindAll(moe, 'getName', 'sayHi');
curly.sayHi = moe.sayHi;
assert.equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
assert.equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
curly = {name: 'curly'};
curly = {name : 'curly'};
moe = {
name: 'moe',
getName: function() { return 'name: ' + this.name; },
sayHi: function() { return 'hi: ' + this.name; },
sayLast: function() { return this.sayHi(_.last(arguments)); }
name : 'moe',
getName : function() { return 'name: ' + this.name; },
sayHi : function() { return 'hi: ' + this.name; },
sayLast : function() { return this.sayHi(_.last(arguments)); }
};
assert.raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
assert.raises(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined');
assert.raises(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function');
throws(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
throws(function() { _.bindAll(moe, 'sayBye'); }, TypeError, 'throws an error for bindAll if the given key is undefined');
throws(function() { _.bindAll(moe, 'name'); }, TypeError, 'throws an error for bindAll if the given key is not a function');
_.bindAll(moe, 'sayHi', 'sayLast');
curly.sayHi = moe.sayHi;
assert.equal(curly.sayHi(), 'hi: moe');
equal(curly.sayHi(), 'hi: moe');
var sayLast = moe.sayLast;
assert.equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments');
_.bindAll(moe, ['getName']);
var getName = moe.getName;
assert.equal(getName(), 'name: moe', 'flattens arguments into a single list');
equal(sayLast(1, 2, 3, 4, 5, 6, 7, 'Tom'), 'hi: moe', 'createCallback works with any number of arguments');
});
QUnit.test('memoize', function(assert) {
test('memoize', function() {
var fib = function(n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
};
assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
fib = _.memoize(fib); // Redefine `fib` for memoization
assert.equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
var o = function(str) {
return str;
};
var fastO = _.memoize(o);
assert.equal(o('toString'), 'toString', 'checks hasOwnProperty');
assert.equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
equal(o('toString'), 'toString', 'checks hasOwnProperty');
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
// Expose the cache.
var upper = _.memoize(function(s) {
return s.toUpperCase();
});
assert.equal(upper('foo'), 'FOO');
assert.equal(upper('bar'), 'BAR');
assert.deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'});
equal(upper('foo'), 'FOO');
equal(upper('bar'), 'BAR');
deepEqual(upper.cache, {foo: 'FOO', bar: 'BAR'});
upper.cache = {foo: 'BAR', bar: 'FOO'};
assert.equal(upper('foo'), 'BAR');
assert.equal(upper('bar'), 'FOO');
equal(upper('foo'), 'BAR');
equal(upper('bar'), 'FOO');
var hashed = _.memoize(function(key) {
//https://github.com/jashkenas/underscore/pull/1679#discussion_r13736209
assert.ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys');
ok(/[a-z]+/.test(key), 'hasher doesn\'t change keys');
return key;
}, function(key) {
return key.toUpperCase();
});
hashed('yep');
assert.deepEqual(hashed.cache, {YEP: 'yep'}, 'takes a hasher');
deepEqual(hashed.cache, {'YEP': 'yep'}, 'takes a hasher');
// Test that the hash function can be used to swizzle the key.
var objCacher = _.memoize(function(value, key) {
@@ -170,94 +155,78 @@
});
var myObj = objCacher('a', 'alpha');
var myObjAlias = objCacher('b', 'alpha');
assert.notStrictEqual(myObj, void 0, 'object is created if second argument used as key');
assert.strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key');
assert.strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key');
notStrictEqual(myObj, undefined, 'object is created if second argument used as key');
strictEqual(myObj, myObjAlias, 'object is cached if second argument used as key');
strictEqual(myObj.value, 'a', 'object is not modified if second argument used as key');
});
QUnit.test('delay', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('delay', 2, function() {
var delayed = false;
_.delay(function(){ delayed = true; }, 100);
setTimeout(function(){ assert.notOk(delayed, "didn't delay the function quite yet"); }, 50);
setTimeout(function(){ assert.ok(delayed, 'delayed the function'); done(); }, 150);
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
});
QUnit.test('defer', function(assert) {
assert.expect(1);
var done = assert.async();
asyncTest('defer', 1, function() {
var deferred = false;
_.defer(function(bool){ deferred = bool; }, true);
_.delay(function(){ assert.ok(deferred, 'deferred the function'); done(); }, 50);
_.delay(function(){ ok(deferred, 'deferred the function'); start(); }, 50);
});
QUnit.test('throttle', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle', 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 32);
throttledIncr(); throttledIncr();
assert.equal(counter, 1, 'incr was called immediately');
_.delay(function(){ assert.equal(counter, 2, 'incr was throttled'); done(); }, 64);
equal(counter, 1, 'incr was called immediately');
_.delay(function(){ equal(counter, 2, 'incr was throttled'); start(); }, 64);
});
QUnit.test('throttle arguments', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle arguments', 2, function() {
var value = 0;
var update = function(val){ value = val; };
var throttledUpdate = _.throttle(update, 32);
throttledUpdate(1); throttledUpdate(2);
_.delay(function(){ throttledUpdate(3); }, 64);
assert.equal(value, 1, 'updated to latest value');
_.delay(function(){ assert.equal(value, 3, 'updated to latest value'); done(); }, 96);
equal(value, 1, 'updated to latest value');
_.delay(function(){ equal(value, 3, 'updated to latest value'); start(); }, 96);
});
QUnit.test('throttle once', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle once', 2, function() {
var counter = 0;
var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 32);
var result = throttledIncr();
_.delay(function(){
assert.equal(result, 1, 'throttled functions return their value');
assert.equal(counter, 1, 'incr was called once'); done();
equal(result, 1, 'throttled functions return their value');
equal(counter, 1, 'incr was called once'); start();
}, 64);
});
QUnit.test('throttle twice', function(assert) {
assert.expect(1);
var done = assert.async();
asyncTest('throttle twice', 1, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 32);
throttledIncr(); throttledIncr();
_.delay(function(){ assert.equal(counter, 2, 'incr was called twice'); done(); }, 64);
_.delay(function(){ equal(counter, 2, 'incr was called twice'); start(); }, 64);
});
QUnit.test('more throttling', function(assert) {
assert.expect(3);
var done = assert.async();
asyncTest('more throttling', 3, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 30);
throttledIncr(); throttledIncr();
assert.equal(counter, 1);
equal(counter, 1);
_.delay(function(){
assert.equal(counter, 2);
equal(counter, 2);
throttledIncr();
assert.equal(counter, 3);
done();
equal(counter, 3);
start();
}, 85);
});
QUnit.test('throttle repeatedly with results', function(assert) {
assert.expect(6);
var done = assert.async();
asyncTest('throttle repeatedly with results', 6, function() {
var counter = 0;
var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 100);
@@ -269,19 +238,17 @@
_.delay(saveResult, 160);
_.delay(saveResult, 230);
_.delay(function() {
assert.equal(results[0], 1, 'incr was called once');
assert.equal(results[1], 1, 'incr was throttled');
assert.equal(results[2], 1, 'incr was throttled');
assert.equal(results[3], 2, 'incr was called twice');
assert.equal(results[4], 2, 'incr was throttled');
assert.equal(results[5], 3, 'incr was called trailing');
done();
equal(results[0], 1, 'incr was called once');
equal(results[1], 1, 'incr was throttled');
equal(results[2], 1, 'incr was throttled');
equal(results[3], 2, 'incr was called twice');
equal(results[4], 2, 'incr was throttled');
equal(results[5], 3, 'incr was called trailing');
start();
}, 300);
});
QUnit.test('throttle triggers trailing call when invoked repeatedly', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle triggers trailing call when invoked repeatedly', 2, function() {
var counter = 0;
var limit = 48;
var incr = function(){ counter++; };
@@ -292,33 +259,29 @@
throttledIncr();
}
var lastCount = counter;
assert.ok(counter > 1);
ok(counter > 1);
_.delay(function() {
assert.ok(counter > lastCount);
done();
ok(counter > lastCount);
start();
}, 96);
});
QUnit.test('throttle does not trigger leading call when leading is set to false', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle does not trigger leading call when leading is set to false', 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 60, {leading: false});
throttledIncr(); throttledIncr();
assert.equal(counter, 0);
equal(counter, 0);
_.delay(function() {
assert.equal(counter, 1);
done();
equal(counter, 1);
start();
}, 96);
});
QUnit.test('more throttle does not trigger leading call when leading is set to false', function(assert) {
assert.expect(3);
var done = assert.async();
asyncTest('more throttle does not trigger leading call when leading is set to false', 3, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100, {leading: false});
@@ -327,83 +290,75 @@
_.delay(throttledIncr, 50);
_.delay(throttledIncr, 60);
_.delay(throttledIncr, 200);
assert.equal(counter, 0);
equal(counter, 0);
_.delay(function() {
assert.equal(counter, 1);
equal(counter, 1);
}, 250);
_.delay(function() {
assert.equal(counter, 2);
done();
equal(counter, 2);
start();
}, 350);
});
QUnit.test('one more throttle with leading: false test', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('one more throttle with leading: false test', 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100, {leading: false});
var time = new Date;
while (new Date - time < 350) throttledIncr();
assert.ok(counter <= 3);
ok(counter <= 3);
_.delay(function() {
assert.ok(counter <= 4);
done();
ok(counter <= 4);
start();
}, 200);
});
QUnit.test('throttle does not trigger trailing call when trailing is set to false', function(assert) {
assert.expect(4);
var done = assert.async();
asyncTest('throttle does not trigger trailing call when trailing is set to false', 4, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 60, {trailing: false});
throttledIncr(); throttledIncr(); throttledIncr();
assert.equal(counter, 1);
equal(counter, 1);
_.delay(function() {
assert.equal(counter, 1);
equal(counter, 1);
throttledIncr(); throttledIncr();
assert.equal(counter, 2);
equal(counter, 2);
_.delay(function() {
assert.equal(counter, 2);
done();
equal(counter, 2);
start();
}, 96);
}, 96);
});
QUnit.test('throttle continues to function after system time is set backwards', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle continues to function after system time is set backwards', 2, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100);
var origNowFunc = _.now;
throttledIncr();
assert.equal(counter, 1);
_.now = function() {
equal(counter, 1);
_.now = function () {
return new Date(2013, 0, 1, 1, 1, 1);
};
_.delay(function() {
throttledIncr();
assert.equal(counter, 2);
done();
equal(counter, 2);
start();
_.now = origNowFunc;
}, 200);
});
QUnit.test('throttle re-entrant', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('throttle re-entrant', 2, function() {
var sequence = [
['b1', 'b2'],
['c1', 'c2']
@@ -419,120 +374,50 @@
};
throttledAppend = _.throttle(append, 32);
throttledAppend.call('a1', 'a2');
assert.equal(value, 'a1a2');
equal(value, 'a1a2');
_.delay(function(){
assert.equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully');
done();
equal(value, 'a1a2c1c2b1b2', 'append was throttled successfully');
start();
}, 100);
});
QUnit.test('throttle cancel', function(assert) {
var done = assert.async();
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 32);
throttledIncr();
throttledIncr.cancel();
throttledIncr();
throttledIncr();
assert.equal(counter, 2, 'incr was called immediately');
_.delay(function(){ assert.equal(counter, 3, 'incr was throttled'); done(); }, 64);
});
QUnit.test('throttle cancel with leading: false', function(assert) {
var done = assert.async();
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 32, {leading: false});
throttledIncr();
throttledIncr.cancel();
assert.equal(counter, 0, 'incr was throttled');
_.delay(function(){ assert.equal(counter, 0, 'incr was throttled'); done(); }, 64);
});
QUnit.test('debounce', function(assert) {
assert.expect(1);
var done = assert.async();
asyncTest('debounce', 1, function() {
var counter = 0;
var incr = function(){ counter++; };
var debouncedIncr = _.debounce(incr, 32);
debouncedIncr(); debouncedIncr();
_.delay(debouncedIncr, 16);
_.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96);
_.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 96);
});
QUnit.test('debounce cancel', function(assert) {
assert.expect(1);
var done = assert.async();
var counter = 0;
var incr = function(){ counter++; };
var debouncedIncr = _.debounce(incr, 32);
debouncedIncr();
debouncedIncr.cancel();
_.delay(function(){ assert.equal(counter, 0, 'incr was not called'); done(); }, 96);
});
QUnit.test('debounce asap', function(assert) {
assert.expect(6);
var done = assert.async();
var a, b, c;
var counter = 0;
var incr = function(){ return ++counter; };
var debouncedIncr = _.debounce(incr, 64, true);
a = debouncedIncr();
b = debouncedIncr();
assert.equal(a, 1);
assert.equal(b, 1);
assert.equal(counter, 1, 'incr was called immediately');
_.delay(debouncedIncr, 16);
_.delay(debouncedIncr, 32);
_.delay(debouncedIncr, 48);
_.delay(function(){
assert.equal(counter, 1, 'incr was debounced');
c = debouncedIncr();
assert.equal(c, 2);
assert.equal(counter, 2, 'incr was called again');
done();
}, 128);
});
QUnit.test('debounce asap cancel', function(assert) {
assert.expect(4);
var done = assert.async();
asyncTest('debounce asap', 4, function() {
var a, b;
var counter = 0;
var incr = function(){ return ++counter; };
var debouncedIncr = _.debounce(incr, 64, true);
a = debouncedIncr();
debouncedIncr.cancel();
b = debouncedIncr();
assert.equal(a, 1);
assert.equal(b, 2);
assert.equal(counter, 2, 'incr was called immediately');
equal(a, 1);
equal(b, 1);
equal(counter, 1, 'incr was called immediately');
_.delay(debouncedIncr, 16);
_.delay(debouncedIncr, 32);
_.delay(debouncedIncr, 48);
_.delay(function(){ assert.equal(counter, 2, 'incr was debounced'); done(); }, 128);
_.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 128);
});
QUnit.test('debounce asap recursively', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('debounce asap recursively', 2, function() {
var counter = 0;
var debouncedIncr = _.debounce(function(){
counter++;
if (counter < 10) debouncedIncr();
}, 32, true);
debouncedIncr();
assert.equal(counter, 1, 'incr was called immediately');
_.delay(function(){ assert.equal(counter, 1, 'incr was debounced'); done(); }, 96);
equal(counter, 1, 'incr was called immediately');
_.delay(function(){ equal(counter, 1, 'incr was debounced'); start(); }, 96);
});
QUnit.test('debounce after system time is set backwards', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('debounce after system time is set backwards', 2, function() {
var counter = 0;
var origNowFunc = _.now;
var debouncedIncr = _.debounce(function(){
@@ -540,23 +425,21 @@
}, 100, true);
debouncedIncr();
assert.equal(counter, 1, 'incr was called immediately');
equal(counter, 1, 'incr was called immediately');
_.now = function() {
_.now = function () {
return new Date(2013, 0, 1, 1, 1, 1);
};
_.delay(function() {
debouncedIncr();
assert.equal(counter, 2, 'incr was debounced successfully');
done();
equal(counter, 2, 'incr was debounced successfully');
start();
_.now = origNowFunc;
}, 200);
});
QUnit.test('debounce re-entrant', function(assert) {
assert.expect(2);
var done = assert.async();
asyncTest('debounce re-entrant', 2, function() {
var sequence = [
['b1', 'b2']
];
@@ -571,81 +454,80 @@
};
debouncedAppend = _.debounce(append, 32);
debouncedAppend.call('a1', 'a2');
assert.equal(value, '');
equal(value, '');
_.delay(function(){
assert.equal(value, 'a1a2b1b2', 'append was debounced successfully');
done();
equal(value, 'a1a2b1b2', 'append was debounced successfully');
start();
}, 100);
});
QUnit.test('once', function(assert) {
test('once', function() {
var num = 0;
var increment = _.once(function(){ return ++num; });
increment();
increment();
assert.equal(num, 1);
equal(num, 1);
assert.equal(increment(), 1, 'stores a memo to the last value');
equal(increment(), 1, 'stores a memo to the last value');
});
QUnit.test('Recursive onced function.', function(assert) {
assert.expect(1);
test('Recursive onced function.', 1, function() {
var f = _.once(function(){
assert.ok(true);
ok(true);
f();
});
f();
});
QUnit.test('wrap', function(assert) {
test('wrap', function() {
var greet = function(name){ return 'hi: ' + name; };
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
assert.equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
var inner = function(){ return 'Hello '; };
var obj = {name: 'Moe'};
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
assert.equal(obj.hi(), 'Hello Moe');
var obj = {name : 'Moe'};
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
equal(obj.hi(), 'Hello Moe');
var noop = function(){};
var noop = function(){};
var wrapped = _.wrap(noop, function(){ return Array.prototype.slice.call(arguments, 0); });
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
assert.deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
});
QUnit.test('negate', function(assert) {
test('negate', function() {
var isOdd = function(n){ return n & 1; };
assert.equal(_.negate(isOdd)(2), true, 'should return the complement of the given function');
assert.equal(_.negate(isOdd)(3), false, 'should return the complement of the given function');
equal(_.negate(isOdd)(2), true, 'should return the complement of the given function');
equal(_.negate(isOdd)(3), false, 'should return the complement of the given function');
});
QUnit.test('compose', function(assert) {
test('compose', function() {
var greet = function(name){ return 'hi: ' + name; };
var exclaim = function(sentence){ return sentence + '!'; };
var composed = _.compose(exclaim, greet);
assert.equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
composed = _.compose(greet, exclaim);
assert.equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
// f(g(h(x, y, z)))
function h(x, y, z) {
assert.equal(arguments.length, 3, 'First function called with multiple args');
equal(arguments.length, 3, 'First function called with multiple args');
return z * y;
}
function g(x) {
assert.equal(arguments.length, 1, 'Composed function is called with 1 argument');
equal(arguments.length, 1, 'Composed function is called with 1 argument');
return x;
}
function f(x) {
assert.equal(arguments.length, 1, 'Composed function is called with 1 argument');
equal(arguments.length, 1, 'Composed function is called with 1 argument');
return x * 2;
}
composed = _.compose(f, g, h);
assert.equal(composed(1, 2, 3), 12);
equal(composed(1, 2, 3), 12);
});
QUnit.test('after', function(assert) {
test('after', function() {
var testAfter = function(afterAmount, timesCalled) {
var afterCalled = 0;
var after = _.after(afterAmount, function() {
@@ -655,13 +537,13 @@
return afterCalled;
};
assert.equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times');
assert.equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times');
assert.equal(testAfter(0, 0), 0, 'after(0) should not fire immediately');
assert.equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked');
equal(testAfter(5, 5), 1, 'after(N) should fire after being called N times');
equal(testAfter(5, 4), 0, 'after(N) should not fire unless called N times');
equal(testAfter(0, 0), 0, 'after(0) should not fire immediately');
equal(testAfter(0, 1), 1, 'after(0) should fire when first invoked');
});
QUnit.test('before', function(assert) {
test('before', function() {
var testBefore = function(beforeAmount, timesCalled) {
var beforeCalled = 0;
var before = _.before(beforeAmount, function() { beforeCalled++; });
@@ -669,97 +551,31 @@
return beforeCalled;
};
assert.equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times');
assert.equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times');
assert.equal(testBefore(0, 0), 0, 'before(0) should not fire immediately');
assert.equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked');
equal(testBefore(5, 5), 4, 'before(N) should not fire after being called N times');
equal(testBefore(5, 4), 4, 'before(N) should fire before being called N times');
equal(testBefore(0, 0), 0, 'before(0) should not fire immediately');
equal(testBefore(0, 1), 0, 'before(0) should not fire when first invoked');
var context = {num: 0};
var increment = _.before(3, function(){ return ++this.num; });
_.times(10, increment, context);
assert.equal(increment(), 2, 'stores a memo to the last value');
assert.equal(context.num, 2, 'provides context');
equal(increment(), 2, 'stores a memo to the last value');
equal(context.num, 2, 'provides context');
});
QUnit.test('iteratee', function(assert) {
test('iteratee', function() {
var identity = _.iteratee();
assert.equal(identity, _.identity, '_.iteratee is exposed as an external function.');
equal(identity, _.identity, '_.iteratee is exposed as an external function.');
function fn() {
return arguments;
}
_.each([_.iteratee(fn), _.iteratee(fn, {})], function(cb) {
assert.equal(cb().length, 0);
assert.deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4));
assert.deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11));
equal(cb().length, 0);
deepEqual(_.toArray(cb(1, 2, 3)), _.range(1, 4));
deepEqual(_.toArray(cb(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), _.range(1, 11));
});
// Test custom iteratee
var builtinIteratee = _.iteratee;
_.iteratee = function(value) {
// RegEx values return a function that returns the number of matches
if (_.isRegExp(value)) return function(obj) {
return (obj.match(value) || []).length;
};
return value;
};
var collection = ['foo', 'bar', 'bbiz'];
// Test all methods that claim to be transformed through `_.iteratee`
assert.deepEqual(_.countBy(collection, /b/g), {0: 1, 1: 1, 2: 1});
assert.equal(_.every(collection, /b/g), false);
assert.deepEqual(_.filter(collection, /b/g), ['bar', 'bbiz']);
assert.equal(_.find(collection, /b/g), 'bar');
assert.equal(_.findIndex(collection, /b/g), 1);
assert.equal(_.findKey(collection, /b/g), 1);
assert.equal(_.findLastIndex(collection, /b/g), 2);
assert.deepEqual(_.groupBy(collection, /b/g), {0: ['foo'], 1: ['bar'], 2: ['bbiz']});
assert.deepEqual(_.indexBy(collection, /b/g), {0: 'foo', 1: 'bar', 2: 'bbiz'});
assert.deepEqual(_.map(collection, /b/g), [0, 1, 2]);
assert.equal(_.max(collection, /b/g), 'bbiz');
assert.equal(_.min(collection, /b/g), 'foo');
assert.deepEqual(_.partition(collection, /b/g), [['bar', 'bbiz'], ['foo']]);
assert.deepEqual(_.reject(collection, /b/g), ['foo']);
assert.equal(_.some(collection, /b/g), true);
assert.deepEqual(_.sortBy(collection, /b/g), ['foo', 'bar', 'bbiz']);
assert.equal(_.sortedIndex(collection, 'blah', /b/g), 1);
assert.deepEqual(_.uniq(collection, /b/g), ['foo', 'bar', 'bbiz']);
var objCollection = {a: 'foo', b: 'bar', c: 'bbiz'};
assert.deepEqual(_.mapObject(objCollection, /b/g), {a: 0, b: 1, c: 2});
// Restore the builtin iteratee
_.iteratee = builtinIteratee;
});
QUnit.test('restArgs', function(assert) {
assert.expect(10);
_.restArgs(function(a, args) {
assert.strictEqual(a, 1);
assert.deepEqual(args, [2, 3], 'collects rest arguments into an array');
})(1, 2, 3);
_.restArgs(function(a, args) {
assert.strictEqual(a, void 0);
assert.deepEqual(args, [], 'passes empty array if there are not enough arguments');
})();
_.restArgs(function(a, b, c, args) {
assert.strictEqual(arguments.length, 4);
assert.deepEqual(args, [4, 5], 'works on functions with many named parameters');
})(1, 2, 3, 4, 5);
var obj = {};
_.restArgs(function() {
assert.strictEqual(this, obj, 'invokes function with this context');
}).call(obj);
_.restArgs(function(array, iteratee, context) {
assert.deepEqual(array, [1, 2, 3, 4], 'startIndex can be used manually specify index of rest parameter');
assert.strictEqual(iteratee, void 0);
assert.strictEqual(context, void 0);
}, 0)(1, 2, 3, 4);
});
}());

File diff suppressed because it is too large Load Diff

View File

@@ -4,218 +4,181 @@
QUnit.module('Utility', {
beforeEach: function() {
setup: function() {
templateSettings = _.clone(_.templateSettings);
},
afterEach: function() {
teardown: function() {
_.templateSettings = templateSettings;
}
});
if (typeof this == 'object') {
QUnit.test('noConflict', function(assert) {
var underscore = _.noConflict();
assert.equal(underscore.identity(1), 1);
if (typeof require != 'function') {
assert.equal(this._, void 0, 'global underscore is removed');
this._ = underscore;
} else if (typeof global !== 'undefined') {
delete global._;
}
});
}
if (typeof require == 'function') {
QUnit.test('noConflict (node vm)', function(assert) {
assert.expect(2);
var done = assert.async();
var fs = require('fs');
var vm = require('vm');
var filename = __dirname + '/../underscore.js';
fs.readFile(filename, function(err, content){
var sandbox = vm.createScript(
content + 'this.underscore = this._.noConflict();',
filename
);
var context = {_: 'oldvalue'};
sandbox.runInNewContext(context);
assert.equal(context._, 'oldvalue');
assert.equal(context.underscore.VERSION, _.VERSION);
done();
});
});
}
QUnit.test('#750 - Return _ instance.', function(assert) {
assert.expect(2);
test('#750 - Return _ instance.', 2, function() {
var instance = _([]);
assert.strictEqual(_(instance), instance);
assert.strictEqual(new _(instance), instance);
ok(_(instance) === instance);
ok(new _(instance) === instance);
});
QUnit.test('identity', function(assert) {
var stooge = {name: 'moe'};
assert.equal(_.identity(stooge), stooge, 'stooge is the same as his identity');
test('identity', function() {
var stooge = {name : 'moe'};
equal(_.identity(stooge), stooge, 'stooge is the same as his identity');
});
QUnit.test('constant', function(assert) {
var stooge = {name: 'moe'};
assert.equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge');
test('constant', function() {
var stooge = {name : 'moe'};
equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge');
});
QUnit.test('noop', function(assert) {
assert.strictEqual(_.noop('curly', 'larry', 'moe'), void 0, 'should always return undefined');
test('noop', function() {
strictEqual(_.noop('curly', 'larry', 'moe'), undefined, 'should always return undefined');
});
QUnit.test('property', function(assert) {
var stooge = {name: 'moe'};
assert.equal(_.property('name')(stooge), 'moe', 'should return the property with the given name');
assert.equal(_.property('name')(null), void 0, 'should return undefined for null values');
assert.equal(_.property('name')(void 0), void 0, 'should return undefined for undefined values');
test('property', function() {
var stooge = {name : 'moe'};
equal(_.property('name')(stooge), 'moe', 'should return the property with the given name');
equal(_.property('name')(null), undefined, 'should return undefined for null values');
equal(_.property('name')(undefined), undefined, 'should return undefined for undefined values');
});
QUnit.test('propertyOf', function(assert) {
test('propertyOf', function() {
var stoogeRanks = _.propertyOf({curly: 2, moe: 1, larry: 3});
assert.equal(stoogeRanks('curly'), 2, 'should return the property with the given name');
assert.equal(stoogeRanks(null), void 0, 'should return undefined for null values');
assert.equal(stoogeRanks(void 0), void 0, 'should return undefined for undefined values');
equal(stoogeRanks('curly'), 2, 'should return the property with the given name');
equal(stoogeRanks(null), undefined, 'should return undefined for null values');
equal(stoogeRanks(undefined), undefined, 'should return undefined for undefined values');
function MoreStooges() { this.shemp = 87; }
MoreStooges.prototype = {curly: 2, moe: 1, larry: 3};
var moreStoogeRanks = _.propertyOf(new MoreStooges());
assert.equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain');
equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain');
var nullPropertyOf = _.propertyOf(null);
assert.equal(nullPropertyOf('curly'), void 0, 'should return undefined when obj is null');
var undefPropertyOf = _.propertyOf(void 0);
assert.equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined');
equal(nullPropertyOf('curly'), undefined, 'should return undefined when obj is null');
var undefPropertyOf = _.propertyOf(undefined);
equal(undefPropertyOf('curly'), undefined, 'should return undefined when obj is undefined');
});
QUnit.test('random', function(assert) {
test('random', function() {
var array = _.range(1000);
var min = Math.pow(2, 31);
var max = Math.pow(2, 62);
assert.ok(_.every(array, function() {
ok(_.every(array, function() {
return _.random(min, max) >= min;
}), 'should produce a random number greater than or equal to the minimum number');
assert.ok(_.some(array, function() {
ok(_.some(array, function() {
return _.random(Number.MAX_VALUE) > 0;
}), 'should produce a random number when passed `Number.MAX_VALUE`');
});
QUnit.test('now', function(assert) {
test('now', function() {
var diff = _.now() - new Date().getTime();
assert.ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms
ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms
});
QUnit.test('uniqueId', function(assert) {
test('uniqueId', function() {
var ids = [], i = 0;
while (i++ < 100) ids.push(_.uniqueId());
assert.equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
});
QUnit.test('times', function(assert) {
test('times', function() {
var vals = [];
_.times(3, function(i) { vals.push(i); });
assert.deepEqual(vals, [0, 1, 2], 'is 0 indexed');
_.times(3, function (i) { vals.push(i); });
deepEqual(vals, [0, 1, 2], 'is 0 indexed');
//
vals = [];
_(3).times(function(i) { vals.push(i); });
assert.deepEqual(vals, [0, 1, 2], 'works as a wrapper');
deepEqual(vals, [0, 1, 2], 'works as a wrapper');
// collects return values
assert.deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values');
deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values');
assert.deepEqual(_.times(0, _.identity), []);
assert.deepEqual(_.times(-1, _.identity), []);
assert.deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
deepEqual(_.times(0, _.identity), []);
deepEqual(_.times(-1, _.identity), []);
deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
});
QUnit.test('mixin', function(assert) {
var ret = _.mixin({
test('mixin', function() {
_.mixin({
myReverse: function(string) {
return string.split('').reverse().join('');
}
});
assert.equal(ret, _, 'returns the _ object to facilitate chaining');
assert.equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
assert.equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
});
QUnit.test('_.escape', function(assert) {
assert.equal(_.escape(null), '');
test('_.escape', function() {
equal(_.escape(null), '');
});
QUnit.test('_.unescape', function(assert) {
test('_.unescape', function() {
var string = 'Curly & Moe';
assert.equal(_.unescape(null), '');
assert.equal(_.unescape(_.escape(string)), string);
assert.equal(_.unescape(string), string, 'don\'t unescape unnecessarily');
equal(_.unescape(null), '');
equal(_.unescape(_.escape(string)), string);
equal(_.unescape(string), string, 'don\'t unescape unnecessarily');
});
// Don't care what they escape them to just that they're escaped and can be unescaped
QUnit.test('_.escape & unescape', function(assert) {
test('_.escape & unescape', function() {
// test & (&amp;) seperately obviously
var escapeCharacters = ['<', '>', '"', '\'', '`'];
_.each(escapeCharacters, function(escapeChar) {
var s = 'a ' + escapeChar + ' string escaped';
var e = _.escape(s);
assert.notEqual(s, e, escapeChar + ' is escaped');
assert.equal(s, _.unescape(e), escapeChar + ' can be unescaped');
var str = 'a ' + escapeChar + ' string escaped';
var escaped = _.escape(str);
notEqual(str, escaped, escapeChar + ' is escaped');
equal(str, _.unescape(escaped), escapeChar + ' can be unescaped');
s = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar;
e = _.escape(s);
str = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar;
escaped = _.escape(str);
assert.equal(e.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar);
assert.equal(_.unescape(e), s, 'multiple occurrences of ' + escapeChar + ' can be unescaped');
equal(escaped.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar);
equal(_.unescape(escaped), str, 'multiple occurrences of ' + escapeChar + ' can be unescaped');
});
// handles multiple escape characters at once
var joiner = ' other stuff ';
var allEscaped = escapeCharacters.join(joiner);
allEscaped += allEscaped;
assert.ok(_.every(escapeCharacters, function(escapeChar) {
ok(_.every(escapeCharacters, function(escapeChar) {
return allEscaped.indexOf(escapeChar) !== -1;
}), 'handles multiple characters');
assert.ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time');
ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time');
// test & -> &amp;
var str = 'some string & another string & yet another';
var escaped = _.escape(str);
assert.notStrictEqual(escaped.indexOf('&'), -1, 'handles & aka &amp;');
assert.equal(_.unescape(str), str, 'can unescape &amp;');
ok(escaped.indexOf('&') !== -1, 'handles & aka &amp;');
equal(_.unescape(str), str, 'can unescape &amp;');
});
QUnit.test('template', function(assert) {
test('template', function() {
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
var result = basicTemplate({thing: 'This'});
assert.equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
var result = basicTemplate({thing : 'This'});
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
var sansSemicolonTemplate = _.template('A <% this %> B');
assert.equal(sansSemicolonTemplate(), 'A B');
equal(sansSemicolonTemplate(), 'A B');
var backslashTemplate = _.template('<%= thing %> is \\ridanculous');
assert.equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous');
equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous');
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
assert.equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
var fancyTemplate = _.template('<ul><% ' +
' for (var key in people) { ' +
'%><li><%= people[key] %></li><% } %></ul>');
result = fancyTemplate({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
result = fancyTemplate({people : {moe : 'Moe', larry : 'Larry', curly : 'Curly'}});
equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
var escapedCharsInJavascriptTemplate = _.template('<ul><% _.each(numbers.split("\\n"), function(item) { %><li><%= item %></li><% }) %></ul>');
result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'});
assert.equal(result, '<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>', 'Can use escaped characters (e.g. \\n) in JavaScript');
equal(result, '<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>', 'Can use escaped characters (e.g. \\n) in JavaScript');
var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class="thumbnail" rel="<%= p %>"></div><% }); %>');
result = namespaceCollisionTemplate({
@@ -226,32 +189,32 @@
3: 'p3-thumbnail.gif'
}
});
assert.equal(result, '3 p3-thumbnail.gif <div class="thumbnail" rel="p1-thumbnail.gif"></div><div class="thumbnail" rel="p2-thumbnail.gif"></div><div class="thumbnail" rel="p3-thumbnail.gif"></div>');
equal(result, '3 p3-thumbnail.gif <div class="thumbnail" rel="p1-thumbnail.gif"></div><div class="thumbnail" rel="p2-thumbnail.gif"></div><div class="thumbnail" rel="p3-thumbnail.gif"></div>');
var noInterpolateTemplate = _.template('<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
result = noInterpolateTemplate();
assert.equal(result, '<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
equal(result, '<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>');
var quoteTemplate = _.template("It's its, not it's");
assert.equal(quoteTemplate({}), "It's its, not it's");
equal(quoteTemplate({}), "It's its, not it's");
var quoteInStatementAndBody = _.template('<% ' +
" if(foo == 'bar'){ " +
"%>Statement quotes and 'quotes'.<% } %>");
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
assert.equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
var template = _.template('<i><%- value %></i>');
result = template({value: '<script>'});
assert.equal(result, '<i>&lt;script&gt;</i>');
equal(result, '<i>&lt;script&gt;</i>');
var stooge = {
name: 'Moe',
template: _.template("I'm <%= this.name %>")
};
assert.equal(stooge.template(), "I'm Moe");
equal(stooge.template(), "I'm Moe");
template = _.template('\n ' +
' <%\n ' +
@@ -259,163 +222,159 @@
' if (data) { data += 12345; }; %>\n ' +
' <li><%= data %></li>\n '
);
assert.equal(template({data: 12345}).replace(/\s/g, ''), '<li>24690</li>');
equal(template({data : 12345}).replace(/\s/g, ''), '<li>24690</li>');
_.templateSettings = {
evaluate: /\{\{([\s\S]+?)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g
evaluate : /\{\{([\s\S]+?)\}\}/g,
interpolate : /\{\{=([\s\S]+?)\}\}/g
};
var custom = _.template('<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>');
result = custom({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
result = custom({people : {moe : 'Moe', larry : 'Larry', curly : 'Curly'}});
equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
var customQuote = _.template("It's its, not it's");
assert.equal(customQuote({}), "It's its, not it's");
equal(customQuote({}), "It's its, not it's");
quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
_.templateSettings = {
evaluate: /<\?([\s\S]+?)\?>/g,
interpolate: /<\?=([\s\S]+?)\?>/g
evaluate : /<\?([\s\S]+?)\?>/g,
interpolate : /<\?=([\s\S]+?)\?>/g
};
var customWithSpecialChars = _.template('<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>');
result = customWithSpecialChars({people: {moe: 'Moe', larry: 'Larry', curly: 'Curly'}});
assert.equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
result = customWithSpecialChars({people : {moe : 'Moe', larry : 'Larry', curly : 'Curly'}});
equal(result, '<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>', 'can run arbitrary javascript in templates');
var customWithSpecialCharsQuote = _.template("It's its, not it's");
assert.equal(customWithSpecialCharsQuote({}), "It's its, not it's");
equal(customWithSpecialCharsQuote({}), "It's its, not it's");
quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
assert.equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'.");
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
interpolate : /\{\{(.+?)\}\}/g
};
var mustache = _.template('Hello {{planet}}!');
assert.equal(mustache({planet: 'World'}), 'Hello World!', 'can mimic mustache.js');
equal(mustache({planet : 'World'}), 'Hello World!', 'can mimic mustache.js');
var templateWithNull = _.template('a null undefined {{planet}}');
assert.equal(templateWithNull({planet: 'world'}), 'a null undefined world', 'can handle missing escape and evaluate settings');
equal(templateWithNull({planet : 'world'}), 'a null undefined world', 'can handle missing escape and evaluate settings');
});
QUnit.test('_.template provides the generated function source, when a SyntaxError occurs', function(assert) {
var source;
test('_.template provides the generated function source, when a SyntaxError occurs', function() {
try {
_.template('<b><%= if x %></b>');
} catch (ex) {
source = ex.source;
var source = ex.source;
}
assert.ok(/__p/.test(source));
ok(/__p/.test(source));
});
QUnit.test('_.template handles \\u2028 & \\u2029', function(assert) {
test('_.template handles \\u2028 & \\u2029', function() {
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
assert.strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
});
QUnit.test('result calls functions and returns primitives', function(assert) {
test('result calls functions and returns primitives', function() {
var obj = {w: '', x: 'x', y: function(){ return this.x; }};
assert.strictEqual(_.result(obj, 'w'), '');
assert.strictEqual(_.result(obj, 'x'), 'x');
assert.strictEqual(_.result(obj, 'y'), 'x');
assert.strictEqual(_.result(obj, 'z'), void 0);
assert.strictEqual(_.result(null, 'x'), void 0);
strictEqual(_.result(obj, 'w'), '');
strictEqual(_.result(obj, 'x'), 'x');
strictEqual(_.result(obj, 'y'), 'x');
strictEqual(_.result(obj, 'z'), undefined);
strictEqual(_.result(null, 'x'), undefined);
});
QUnit.test('result returns a default value if object is null or undefined', function(assert) {
assert.strictEqual(_.result(null, 'b', 'default'), 'default');
assert.strictEqual(_.result(void 0, 'c', 'default'), 'default');
assert.strictEqual(_.result(''.match('missing'), 1, 'default'), 'default');
test('result returns a default value if object is null or undefined', function() {
strictEqual(_.result(null, 'b', 'default'), 'default');
strictEqual(_.result(undefined, 'c', 'default'), 'default');
strictEqual(_.result(''.match('missing'), 1, 'default'), 'default');
});
QUnit.test('result returns a default value if property of object is missing', function(assert) {
assert.strictEqual(_.result({d: null}, 'd', 'default'), null);
assert.strictEqual(_.result({e: false}, 'e', 'default'), false);
test('result returns a default value if property of object is missing', function() {
strictEqual(_.result({d: null}, 'd', 'default'), null);
strictEqual(_.result({e: false}, 'e', 'default'), false);
});
QUnit.test('result only returns the default value if the object does not have the property or is undefined', function(assert) {
assert.strictEqual(_.result({}, 'b', 'default'), 'default');
assert.strictEqual(_.result({d: void 0}, 'd', 'default'), 'default');
test('result only returns the default value if the object does not have the property or is undefined', function() {
strictEqual(_.result({}, 'b', 'default'), 'default');
strictEqual(_.result({d: undefined}, 'd', 'default'), 'default');
});
QUnit.test('result does not return the default if the property of an object is found in the prototype', function(assert) {
test('result does not return the default if the property of an object is found in the prototype', function() {
var Foo = function(){};
Foo.prototype.bar = 1;
assert.strictEqual(_.result(new Foo, 'bar', 2), 1);
strictEqual(_.result(new Foo, 'bar', 2), 1);
});
QUnit.test('result does use the fallback when the result of invoking the property is undefined', function(assert) {
test('result does use the fallback when the result of invoking the property is undefined', function() {
var obj = {a: function() {}};
assert.strictEqual(_.result(obj, 'a', 'failed'), void 0);
strictEqual(_.result(obj, 'a', 'failed'), undefined);
});
QUnit.test('result fallback can use a function', function(assert) {
test('result fallback can use a function', function() {
var obj = {a: [1, 2, 3]};
assert.strictEqual(_.result(obj, 'b', _.constant(5)), 5);
assert.strictEqual(_.result(obj, 'b', function() {
strictEqual(_.result(obj, 'b', _.constant(5)), 5);
strictEqual(_.result(obj, 'b', function() {
return this.a;
}), obj.a, 'called with context');
});
QUnit.test('_.templateSettings.variable', function(assert) {
test('_.templateSettings.variable', function() {
var s = '<%=data.x%>';
var data = {x: 'x'};
var tmp = _.template(s, {variable: 'data'});
assert.strictEqual(tmp(data), 'x');
strictEqual(tmp(data), 'x');
_.templateSettings.variable = 'data';
assert.strictEqual(_.template(s)(data), 'x');
strictEqual(_.template(s)(data), 'x');
});
QUnit.test('#547 - _.templateSettings is unchanged by custom settings.', function(assert) {
assert.notOk(_.templateSettings.variable);
test('#547 - _.templateSettings is unchanged by custom settings.', function() {
ok(!_.templateSettings.variable);
_.template('', {}, {variable: 'x'});
assert.notOk(_.templateSettings.variable);
ok(!_.templateSettings.variable);
});
QUnit.test('#556 - undefined template variables.', function(assert) {
test('#556 - undefined template variables.', function() {
var template = _.template('<%=x%>');
assert.strictEqual(template({x: null}), '');
assert.strictEqual(template({x: void 0}), '');
strictEqual(template({x: null}), '');
strictEqual(template({x: undefined}), '');
var templateEscaped = _.template('<%-x%>');
assert.strictEqual(templateEscaped({x: null}), '');
assert.strictEqual(templateEscaped({x: void 0}), '');
strictEqual(templateEscaped({x: null}), '');
strictEqual(templateEscaped({x: undefined}), '');
var templateWithProperty = _.template('<%=x.foo%>');
assert.strictEqual(templateWithProperty({x: {}}), '');
assert.strictEqual(templateWithProperty({x: {}}), '');
strictEqual(templateWithProperty({x: {}}), '');
strictEqual(templateWithProperty({x: {}}), '');
var templateWithPropertyEscaped = _.template('<%-x.foo%>');
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
assert.strictEqual(templateWithPropertyEscaped({x: {}}), '');
strictEqual(templateWithPropertyEscaped({x: {}}), '');
strictEqual(templateWithPropertyEscaped({x: {}}), '');
});
QUnit.test('interpolate evaluates code only once.', function(assert) {
assert.expect(2);
test('interpolate evaluates code only once.', 2, function() {
var count = 0;
var template = _.template('<%= f() %>');
template({f: function(){ assert.notOk(count++); }});
template({f: function(){ ok(!count++); }});
var countEscaped = 0;
var templateEscaped = _.template('<%- f() %>');
templateEscaped({f: function(){ assert.notOk(countEscaped++); }});
templateEscaped({f: function(){ ok(!countEscaped++); }});
});
QUnit.test('#746 - _.template settings are not modified.', function(assert) {
assert.expect(1);
test('#746 - _.template settings are not modified.', 1, function() {
var settings = {};
_.template('', null, settings);
assert.deepEqual(settings, {});
deepEqual(settings, {});
});
QUnit.test('#779 - delimeters are applied to unescaped text.', function(assert) {
assert.expect(1);
test('#779 - delimeters are applied to unescaped text.', 1, function() {
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
assert.strictEqual(template(), '<<\nx\n>>');
strictEqual(template(), '<<\nx\n>>');
});
}());

File diff suppressed because it is too large Load Diff

3346
yarn.lock

File diff suppressed because it is too large Load Diff