Compare commits

..

1 Commits
2.3.0 ... 1.3.0

Author SHA1 Message Date
Benjamin Tan
7ac57c2785 Update v1.3.0 docs 2015-01-23 15:50:13 +08:00
86 changed files with 19421 additions and 23271 deletions

4
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
* text=auto
*.html text eol=lf
*.js text eol=lf
*.md text eol=lf
*.jst text eol=lf
*.sh text eol=lf
*.tpl text eol=lf

8
.gitignore vendored
View File

@@ -1,10 +1,8 @@
.DS_Store
*.custom.*
*.template.*
*.d.ts
*.map
/*.min.*
modularize
node_modules
dist/*.backbone.*
dist/*.legacy.*
dist/*.mobile.*
vendor/closure-compiler
vendor/uglifyjs

18
.jamignore Normal file
View File

@@ -0,0 +1,18 @@
.*
*.custom.*
*.template.*
*.d.ts
*.map
*.md
*.txt
build.js
lodash.js
index.js
bower.json
component.json
build
doc
node_modules
perf
test
vendor

25
.npmignore Normal file
View File

@@ -0,0 +1,25 @@
.*
*.custom.*
*.template.*
*.d.ts
*.map
*.md
bower.json
component.json
doc
perf
test
vendor/*.gz
vendor/backbone
vendor/benchmark.js
vendor/closure-compiler
vendor/docdown
vendor/firebug-lite
vendor/jquery
vendor/json3
vendor/platform.js
vendor/qunit
vendor/qunit-clib
vendor/requirejs
vendor/uglifyjs
vendor/underscore

View File

@@ -1,80 +1,23 @@
language: node_js
node_js:
- "0.6"
- "0.8"
- "0.10"
- 0.6
- 0.9
- 0.10
env:
global:
- BIN="node" BUILD=false COMPAT=false MAKE=false OPTION="" SAUCE_LABS=false
- SAUCE_USERNAME="jdalton"
- secure: "woILQltl1pI3DgadZ5NrcqntdPvnRmQBwIVNZL91Ht5d9snIhgyAixI6xNAS8F8BzD9RzqzVPHay5sHfn+GhNaojcaiHs1nXAbdyclevMyfP+3MQ1HGfMSU0bv1GdT35LJ+C0u4Y3SuuZSbBlNEeLXRPMngPZahf4xL8RsZz/is="
matrix:
- BUILD="compat"
- BUILD="modern"
- BUILD="legacy"
- BUILD="mobile"
- BIN="phantomjs" BUILD="compat"
- BIN="phantomjs" BUILD="legacy"
- BIN="phantomjs" BUILD="mobile"
matrix:
include:
- node_js: "0.10"
env: BIN="istanbul"
- node_js: "0.10"
env: BIN="narwhal" BUILD="compat"
- node_js: "0.10"
env: BIN="narwhal" BUILD="legacy"
- node_js: "0.10"
env: BIN="rhino" BUILD="compat"
- node_js: "0.10"
env: BIN="rhino" BUILD="legacy"
- node_js: "0.10"
env: BIN="rhino" BUILD="compat" OPTION="-require"
- node_js: "0.10"
env: BIN="rhino" BUILD="legacy" OPTION="-require"
- node_js: "0.10"
env: BIN="ringo" BUILD="compat"
- node_js: "0.10"
env: BIN="ringo" BUILD="legacy"
- node_js: "0.8"
env: SAUCE_LABS=true BUILD="compat"
- node_js: "0.8"
env: SAUCE_LABS=true BUILD="modern"
- node_js: "0.8"
env: SAUCE_LABS=true BUILD="legacy"
- node_js: "0.8"
env: SAUCE_LABS=true BUILD="mobile"
- node_js: "0.8"
env: SAUCE_LABS=true BUILD="underscore"
- TEST_COMMAND="istanbul cover ./test/test.js"
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.js"
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.min.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.min.js"
- TEST_COMMAND="node ./test/test-build.js --time-limit 48m"
git:
depth: 10
depth: 1
branches:
only:
- master
before_install:
- "([ $BUILD == 'legacy' ] || [ $BUILD == 'mobile' ] || [ $BUILD == 'modern' ]) && MAKE=true || true"
- "([ $BUILD == 'compat' ] || [ $BUILD == 'legacy' ]) && COMPAT=true || true"
- "[ $SAUCE_LABS != false ] && npm i ecstatic@\"~0.4.0\" request@\"~2.27.0\" sauce-tunnel@\"~1.1.0\" || true"
- "[ $BIN == 'istanbul' ] && npm i -g istanbul@\"~0.1.0\" || true"
- "[ $BIN == 'narwhal' ] && wget https://github.com/280north/narwhal/archive/v0.3.2.zip && sudo unzip v0.3.2 -d /opt/ && rm v0.3.2.zip || true"
- "[ $BIN == 'narwhal' ] && sudo ln -s /opt/narwhal-0.3.2/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal || true"
- "[ $BIN == 'rhino' ] && sudo mkdir /opt/rhino-1.7R5 && sudo wget -O /opt/rhino-1.7R5/js.jar https://oss.sonatype.org/content/repositories/snapshots/org/mozilla/rhino/1.7R5-SNAPSHOT/rhino-1.7R5-20120629.144839-4.jar || true"
- "[ $BIN == 'rhino' ] && echo -e '#!/bin/sh\\njava -jar /opt/rhino-1.7R5/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino || true"
- "[ $BIN == 'ringo' ] && wget http://ringojs.org/downloads/ringojs-0.9.zip && sudo unzip ringojs-0.9 -d /opt && rm ringojs-0.9.zip || true"
- "[ $BIN == 'ringo' ] && sudo ln -s /opt/ringojs-0.9/bin/ringo /usr/local/bin/ringo && sudo chmod +x /usr/local/bin/ringo || true"
- "[ $MAKE != false ] && git clone --depth=10 --branch=master git://github.com/lodash/lodash-cli.git ./node_modules/lodash-cli || true"
- "[ $MAKE != false ] && mkdir ./node_modules/lodash-cli/node_modules && cd ./node_modules/lodash-cli/node_modules/ && ln -s ../../../ ./lodash && cd ../ && npm i . && cd ../../ || true"
- "[ $MAKE != false ] && node ./node_modules/lodash-cli/bin/lodash $BUILD -o ./dist/lodash.$BUILD.js || true"
before_script:
- "tar -xzvf vendor/closure-compiler.tar.gz -C vendor"
- "tar -xzvf vendor/uglifyjs.tar.gz -C vendor"
- "npm install -g istanbul"
script:
- "[ $BIN == 'istanbul' ] && $BIN cover ./test/test.js || true"
- "([ $SAUCE_LABS != false ] || [ $BUILD == false ]) && true || cd ./test"
- "([ $SAUCE_LABS != false ] || [ $BUILD == false ]) && true || $BIN $OPTION ./test.js ../dist/lodash.$BUILD.js"
- "([ $SAUCE_LABS != false ] || [ $BUILD == false ]) && true || $BIN $OPTION ./test.js ../dist/lodash.$BUILD.min.js"
- "([ $SAUCE_LABS == false ] || [ $BUILD == 'underscore' ]) && true || node ./test/saucelabs.js \"test/index.html?build=lodash-$BUILD\""
- "([ $SAUCE_LABS == false ] || [ $BUILD == 'underscore' ]) && true || node ./test/saucelabs.js \"test/index.html?build=../dist/lodash.$BUILD.js\""
- "[ $SAUCE_LABS == false ] && true || node ./test/saucelabs.js \"test/backbone.html?build=lodash-$BUILD\""
- "[ $SAUCE_LABS == false ] && true || node ./test/saucelabs.js \"test/backbone.html?build=../dist/lodash.$BUILD.js\""
- "[ $SAUCE_LABS == false ] && true || node ./test/saucelabs.js \"test/underscore.html?build=lodash-$BUILD\""
- "[ $SAUCE_LABS == false ] && true || node ./test/saucelabs.js \"test/underscore.html?build=../dist/lodash.$BUILD.js\""
- "([ $SAUCE_LABS == false ] || [ $COMPAT == false ]) && true || node ./test/saucelabs.js \"test/index.html?build=lodash-$BUILD&compat=7\""
- "([ $SAUCE_LABS == false ] || [ $COMPAT == false ]) && true || node ./test/saucelabs.js \"test/index.html?build=../dist/lodash.$BUILD.js&compat=7\""
$TEST_COMMAND

View File

@@ -1,12 +1,12 @@
# Contributing to Lo-Dash
If youd like to contribute a feature or bug fix, you can [fork](https://help.github.com/articles/fork-a-repo) Lo-Dash, commit your changes, and [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`.
Please make sure to [search the issue tracker](https://github.com/bestiejs/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.
You can run the tests from the command line via `node test/test`, or open `test/index.html` in a web browser.
You can run the tests from the command line via `npm 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/Rhino), [Narwhal](https://github.com/280north/narwhal), [RingoJS](http://ringojs.org/), [PhantomJS](http://phantomjs.org/), and [Node](http://nodejs.org/), before running them in your default browser.
The [Backbone](http://backbonejs.org/) and [Underscore](http://http://underscorejs.org/) test suites are included as well.
@@ -15,7 +15,7 @@ The [Backbone](http://backbonejs.org/) and [Underscore](http://http://underscore
Lo-Dash 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/).
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

View File

@@ -1,6 +1,6 @@
Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js 1.5.2, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud Inc. <http://underscorejs.org/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

326
README.md
View File

@@ -1,101 +1,194 @@
# Lo-Dash v2.3.0
A utility library delivering consistency, [customization](http://lodash.com/custom-builds), [performance](http://lodash.com/benchmarks), & [extras](http://lodash.com/#features).
# Lo-Dash <sup>v1.3.0</sup>
A low-level utility library delivering consistency, [customization](https://github.com/bestiejs/lodash#custom-builds), [performance](http://lodash.com/benchmarks), and [extra features](https://github.com/bestiejs/lodash#features).
## Download
Check out our [wiki]([https://github.com/lodash/lodash/wiki/build-differences]) for details over the differences between builds.
* Lo-Dash builds (for modern environments):<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.min.js)
* Modern builds perfect for newer browsers/environments:<br>
[Development](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.js) &
[Production](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.min.js)
* Lo-Dash compatibility builds (for legacy and modern environments):<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.compat.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.compat.min.js)
* Compatibility builds for older environment support too:<br>
[Development](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.compat.js) &
[Production](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.compat.min.js)
* Underscore compatibility builds:<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.underscore.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.3.0/dist/lodash.underscore.min.js)
* Underscore builds to use as a drop-in replacement:<br>
[Development](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.underscore.js) &
[Production](https://raw.github.com/lodash/lodash/2.3.0/dist/lodash.underscore.min.js)
* CDN copies of ≤ v1.3.0s builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):<br>
[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.js),
[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.min.js),<br>
[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.compat.js),
[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.compat.min.js),<br>
[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.underscore.js), and
[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.0/lodash.underscore.min.js)
CDN copies are available on [cdnjs](http://cdnjs.com/libraries/lodash.js/) & [jsDelivr](http://www.jsdelivr.com/#!lodash). For smaller file sizes, create [custom builds](http://lodash.com/custom-builds) with only the features needed.
Love modules? Weve got you covered with [lodash-amd](https://npmjs.org/package/lodash-amd), [lodash-es6](https://github.com/lodash/lodash-es6), [lodash-node](https://npmjs.org/package/lodash-node), & [npm packages](https://npmjs.org/browse/keyword/lodash-modularized) per method.
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
## Dive in
Theres plenty of **[documentation](http://lodash.com/docs)**, [unit tests](http://lodash.com/tests), & [benchmarks](http://lodash.com/benchmarks).<br>
Check out <a href="http://devdocs.io/lodash/">DevDocs</a> as a fast, organized, & searchable interface for our documentation.
Weve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
The full changelog for this release is available on our [wiki](https://github.com/lodash/lodash/wiki/Changelog).<br>
A list of upcoming features is available on our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).
## Features *not* in Underscore
* AMD loader support ([curl](https://github.com/cujojs/curl), [dojo](http://dojotoolkit.org/), [requirejs](http://requirejs.org/), etc.)
* [_(…)](http://lodash.com/docs#_) supports intuitive chaining
* [_.at](http://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”*](http://michaux.ca/articles/lazy-function-definition-pattern) defined methods
* [_.clone](http://lodash.com/docs#clone) supports shallow cloning of `Date` & `RegExp` objects
* [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays & objects
* [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex`
* [_.create](http://lodash.com/docs#create) for easier object inheritance
* [_.createCallback](http://lodash.com/docs#createCallback) for extending callbacks in methods & mixins
* [_.curry](http://lodash.com/docs#curry) for creating [curried](http://hughfdjackson.com/javascript/2013/07/06/why-curry-helps/) functions
* [_.debounce](http://lodash.com/docs#debounce) & [_.throttle](http://lodash.com/docs#throttle) accept additional `options` for more control
* [_.findIndex](http://lodash.com/docs#findIndex) & [_.findKey](http://lodash.com/docs#findKey) for finding indexes & keys
* [_.forEach](http://lodash.com/docs#forEach) is chainable & supports exiting early
* [_.forIn](http://lodash.com/docs#forIn) for iterating own & inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating own properties
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) for checking if values are created by `Object`
* [_.memoize](http://lodash.com/docs#memoize) exposes the `cache` of memoized functions
* [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
* [_.noop](http://lodash.com/docs#noop) for function placeholders
* [_.parseInt](http://lodash.com/docs#parseInt) for consistent behavior
* [_.partialRight](http://lodash.com/docs#partialRight) for [partial application](http://lodash.com/docs#partial) from the right
* [_.pull](http://lodash.com/docs#pull) & [_.remove](http://lodash.com/docs#remove) for mutating arrays
* [_.random](http://lodash.com/docs#random) supports returning floating-point numbers
* [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking
* [_.support](http://lodash.com/docs#support) for flagging environment features
* [_.template](http://lodash.com/docs#template) supports [*“imports”*](http://lodash.com/docs#templateSettings_imports) options & [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6)
* [_.transform](http://lodash.com/docs#transform) as a powerful alternative to [_.reduce](http://lodash.com/docs#reduce) for transforming objects
* [_.where](http://lodash.com/docs#where) supports deep object comparisons
* [_.zip](http://lodash.com/docs#zip) is capable of unzipping values
* [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick), &
[more](http://lodash.com/docs "_.assign, _.clone, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept callbacks
* [_.contains](http://lodash.com/docs#contains), [_.toArray](http://lodash.com/docs#toArray), &
[more](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.forEachRight, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.size, _.some, _.sortBy, _.where") accept strings
* [_.filter](http://lodash.com/docs#filter), [_.map](http://lodash.com/docs#map), &
[more](http://lodash.com/docs "_.countBy, _.every, _.find, _.findKey, _.findLast, _.findLastIndex, _.findLastKey, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* & *“_.where”* shorthands
* [_.findLast](http://lodash.com/docs#findLast), [_.findLastIndex](http://lodash.com/docs#findLastIndex), &
[more](http://lodash.com/docs "_.findLastKey, _.forEachRight, _.forInRight, _.forOwnRight") right-associative methods
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
## Resources
* Podcasts
- [JavaScript Jabber](http://javascriptjabber.com/079-jsj-lo-dash-with-john-david-dalton/)
For more information check out these articles, screencasts, and other videos over Lo-Dash:
* Posts
- [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
- [Custom builds in Lo-Dash 2.0](http://kitcambridge.be/blog/custom-builds-in-lo-dash-2-dot-0/)
* Videos
- [Introduction](https://vimeo.com/44154599)
- [Origins](https://vimeo.com/44154600)
- [Optimizations & builds](https://vimeo.com/44154601)
- [Native method use](https://vimeo.com/48576012)
- [Testing](https://vimeo.com/45865290)
- [CascadiaJS 12](http://www.youtube.com/watch?v=dpPy4f_SeEk)
- [Introducing Lo-Dash](https://vimeo.com/44154599)
- [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
- [Lo-Dashs origin and why its a better utility belt](https://vimeo.com/44154600)
- [Unit testing in Lo-Dash](https://vimeo.com/45865290)
- [Lo-Dashs approach to native method use](https://vimeo.com/48576012)
- [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
A list of other community created podcasts, posts, & videos is available on our [wiki](https://github.com/lodash/lodash/wiki/Resources).
## Features
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
* [_(…)](http://lodash.com/docs#_) supports intuitive chaining
* [_.at](http://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
* [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
* [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument
* [_.debounce](http://lodash.com/docs#debounce) and [_.throttle](http://lodash.com/docs#throttle) accept an `options` argument for more control
* [_.createCallback](http://lodash.com/docs#createCallback) to customize how callback arguments are handled and support callback shorthands in mixins
* [_.findIndex](http://lodash.com/docs#findIndex) and [_.findKey](http://lodash.com/docs#findKey) for finding indexes and keys of collections
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an objects own and inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objects own properties
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
* [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
* [_.parseInt](http://lodash.com/docs#parseInt) for consistent cross-environment behavior
* [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding
* [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking and extended environment support
* [_.support](http://lodash.com/docs#support) to flag environment features
* [_.template](http://lodash.com/docs#template) supports [*“imports”* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* [_.transform](http://lodash.com/docs#transform) as a powerful alternative to [_.reduce](http://lodash.com/docs#reduce) for transforming objects
* [_.unzip](http://lodash.com/docs#unzip) as the inverse of [_.zip](http://lodash.com/docs#zip)
* [_.where](http://lodash.com/docs#where) supports deep object comparisons
* [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),
[and more…](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
[and more…](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
* [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),
[and more…](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands
## Support
Tested in Chrome 5~30, Firefox 2~25, IE 6-11, Opera 9.25~17, Safari 3-7, Node.js 0.6.8-0.10.21, Narwhal 0.3.2, PhantomJS 1.9.2, RingoJS 0.9, & Rhino 1.7RC5.
Lo-Dash has been tested in at least Chrome 5~27, Firefox 2~21, IE 6-10, Opera 9.25~12, Safari 3-6, Node.js 0.4.8-0.10.7 (Node bug [#5622](https://github.com/joyent/node/issues/5622) prevents 0.10.8-0.10.10 from working), Narwhal 0.3.2, PhantomJS 1.9.0, RingoJS 0.9, and Rhino 1.7RC5.
Special thanks to [Sauce Labs](https://saucelabs.com/) for providing automated browser testing.<br>
[![Sauce Labs](http://lodash.com/_img/sauce.png)](https://saucelabs.com/ "Sauce Labs: Selenium Testing & More")
## Custom builds
## Installation & usage
Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
To top it off, we handle all method dependency and alias mapping for you.
For a more detailed summary over the differences between various builds, check out the [wiki page](https://github.com/bestiejs/lodash/wiki/build-differences).
* Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.
```bash
lodash backbone
```
* Legacy builds, tailored for older environments without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
```bash
lodash legacy
```
* Modern builds, tailored for newer environments with ES5 support, may be created using the `modern` modifier argument.
```bash
lodash modern
```
* Mobile builds, without method compilation and most bug fixes for old browsers, may be created using the `mobile` modifier argument.
```bash
lodash mobile
```
* Strict builds, with `_.bindAll`, `_.defaults`, and `_.extend` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
```bash
lodash strict
```
* Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.
```bash
lodash underscore
```
Custom builds may be created using the following commands:
* Use the `category` argument to pass comma separated categories of methods to include in the build.<br>
Valid categories (case-insensitive) are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
```bash
lodash category=collections,functions
lodash category="collections, functions"
```
* Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>
Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
```bash
lodash exports=amd,commonjs,node
lodash exports="amd, commonjs, node"
```
* Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
```bash
lodash iife="!function(window,undefined){%output%}(this)"
```
* Use the `include` argument to pass comma separated method/category names to include in the build.
```bash
lodash include=each,filter,map
lodash include="each, filter, map"
```
* Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.
```bash
lodash underscore minus=result,shuffle
lodash underscore minus="result, shuffle"
```
* Use the `plus` argument to pass comma separated method/category names to add to those included in the build.
```bash
lodash backbone plus=random,template
lodash backbone plus="random, template"
```
* Use the `template` argument to pass the file path pattern used to match template files to precompile.
```bash
lodash template="./*.jst"
```
* Use the `settings` argument to pass the template settings used when precompiling templates.
```bash
lodash settings="{interpolate:/\{\{([\s\S]+?)\}\}/g}"
```
* Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates.
```bash
lodash moduleId="underscore"
```
All arguments, except `legacy` with `mobile`, `modern`, or `underscore`, may be combined.<br>
Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
The following options are also supported:
* `-c`, `--stdout` ......... Write output to standard output
* `-d`, `--debug` ........... Write only the non-minified development output
* `-h`, `--help` ............. Display help information
* `-m`, `--minify` ......... Write only the minified production output
* `-o`, `--output` ......... Write output to a given path/filename
* `-p`, `--source-map` .. Generate a source map for the minified output, using an optional source map URL
* `-s`, `--silent` ......... Skip status updates normally logged to the console
* `-V`, `--version` ....... Output current version of Lo-Dash
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
## Installation and usage
In browsers:
@@ -106,23 +199,34 @@ In browsers:
Using [`npm`](http://npmjs.org/):
```bash
npm i --save lodash
npm install lodash
{sudo} npm i -g lodash
npm ln lodash
npm install -g lodash
npm link lodash
```
In [Node.js](http://nodejs.org/) & [Ringo](http://ringojs.org/):
To avoid potential issues, update `npm` before installing Lo-Dash:
```bash
npm install npm -g
```
In [Node.js](http://nodejs.org/) and [RingoJS ≥ v0.8.0](http://ringojs.org/):
```js
var _ = require('lodash');
// or as Underscore
// or as a drop-in replacement for Underscore
var _ = require('lodash/dist/lodash.underscore');
```
**Notes:**
* Dont assign values to [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` when in the REPL
* If Lo-Dash is installed globally, run [`npm ln lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory *before* requiring it
**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory before requiring it.
In [RingoJS ≤ v0.7.0](http://ringojs.org/):
```js
var _ = require('lodash')._;
```
In [Rhino](http://www.mozilla.org/rhino/):
@@ -130,27 +234,69 @@ In [Rhino](http://www.mozilla.org/rhino/):
load('lodash.js');
```
In an AMD loader:
In an AMD loader like [RequireJS](http://requirejs.org/):
```js
require({
'packages': [
{ 'name': 'lodash', 'location': 'path/to/lodash', 'main': 'lodash' }
]
'paths': {
'underscore': 'path/to/lodash'
}
},
['lodash'], function(_) {
['underscore'], function(_) {
console.log(_.VERSION);
});
```
## Release Notes
### <sup>v1.3.0</sup>
* Added `_.transform` method
* Added `_.chain` and `_.findWhere` aliases
* Added internal array and object pooling
* Added Istanbul test coverage reports to Travis CI
* Added `maxWait` option to `_.debounce`
* Added support for floating point numbers to `_.random`
* Added Volo configuration to package.json
* Adjusted UMD for `component build`
* Allowed more stable mixing of `lodash` and `underscore` build methods
* Ensured debounced function with, `leading` and `trailing` options, works as expected
* Ensured minified builds work with the Dojo builder
* Ensured minification avoids deoptimizing expressions containing boolean values
* Ensured unknown types return `false` in `_.isObject` and `_.isRegExp`
* Ensured `_.clone`, `_.flatten`, and `_.uniq` can be used as a `callback` for methods like `_.map`
* Ensured `_.forIn` works on objects with longer inheritance chains in IE < 9
* Ensured `_.isPlainObject` returns `true` for empty objects in IE < 9
* Ensured `_.max` and `_.min` chain correctly
* Ensured `clearTimeout` use doesnt cause errors in Titanium
* Ensured that the `--stdout` build option doesn't write to a file
* Exposed memoized functions `cache`
* Fixed `Error.prototype` iteration bugs
* Fixed "scripts" paths in component.json
* Made methods support customizing `_.indexOf`
* Made the build track dependencies of private functions
* Made the `template` pre-compiler build option avoid escaping non-ascii characters
* Made `_.createCallback` avoid binding functions if they dont reference `this`
* Optimized the Closure Compiler minification process
* Optimized the large array cache for `_.difference`, `_.intersection`, and `_.uniq`
* Optimized internal `_.flatten` and `_.indexOf` use
* Reduced `_.unzip` and `_.zip`
* Removed special handling of arrays in `_.assign` and `_.defaults`
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
## BestieJS
Lo-Dash is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Author
| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") |
| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
|---|
| [John-David Dalton](http://allyoucanleet.com/) |
## Contributors
| [![twitter/blainebublitz](http://gravatar.com/avatar/ac1c67fd906c9fecd823ce302283b4c1?s=70)](https://twitter.com/blainebublitz "Follow @BlaineBublitz on Twitter") | [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|---|---|
| [Blaine Bublitz](http://www.iceddev.com/) | [Kit Cambridge](http://kitcambridge.be/) | [Mathias Bynens](http://mathiasbynens.be/) |
| [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") | [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") |
|---|---|
| [Kit Cambridge](http://kitcambridge.github.io/) | [Mathias Bynens](http://mathiasbynens.be/) |

View File

@@ -1,20 +1,21 @@
{
"name": "lodash",
"version": "2.3.0",
"main": "dist/lodash.compat.js",
"version": "1.3.0",
"main": "./dist/lodash.compat.js",
"ignore": [
".*",
"*.custom.*",
"*.template.*",
"*.d.ts",
"*.map",
"*.md",
"/*.min.*",
"/lodash.js",
"*.txt",
"build.js",
"index.js",
"component.json",
"package.json",
"build",
"doc",
"modularize",
"node_modules",
"perf",
"test",

3531
build.js Executable file

File diff suppressed because it is too large Load Diff

793
build/minify.js Executable file
View File

@@ -0,0 +1,793 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var cp = require('child_process'),
https = require('https'),
zlib = require('zlib');
/** Load other modules */
var _ = require('../lodash.js'),
preprocess = require('./pre-compile.js'),
postprocess = require('./post-compile.js'),
tar = require('../vendor/tar/tar.js'),
util = require('./util.js');
/** Module shortcuts */
var fs = util.fs,
path = util.path;
/** The Git object ID of `closure-compiler.tar.gz` */
var closureId = '9fd5d61c1b706e7505aeb5187941c2c5497e5fd8';
/** The Git object ID of `uglifyjs.tar.gz` */
var uglifyId = '7de2795a3af58d1b293e3b0e83cdbc994f4941dc';
/** The path of the directory that is the base of the repository */
var basePath = fs.realpathSync(path.join(__dirname, '..'));
/** The path of the `vendor` directory */
var vendorPath = path.join(basePath, 'vendor');
/** The path to the Closure Compiler `.jar` */
var closurePath = path.join(vendorPath, 'closure-compiler', 'compiler.jar');
/** The path to the UglifyJS module */
var uglifyPath = path.join(vendorPath, 'uglifyjs', 'tools', 'node.js');
/** The Closure Compiler command-line options */
var closureOptions = ['--warning_level=QUIET'];
/** The media type for raw blob data */
var mediaType = 'application/vnd.github.v3.raw';
/** Used to detect the Node.js executable in command-line arguments */
var reNode = RegExp('(?:^|' + path.sepEscaped + ')node(?:\\.exe)?$');
/** Used to reference parts of the blob href */
var location = (function() {
var host = 'api.github.com',
origin = 'https://api.github.com',
pathname = '/repos/bestiejs/lodash/git/blobs';
return {
'host': host,
'href': origin + pathname,
'origin': origin,
'pathname': pathname
};
}());
/** The Closure Compiler optimization modes */
var optimizationModes = {
'simple': 'SIMPLE_OPTIMIZATIONS',
'advanced': 'ADVANCED_OPTIMIZATIONS'
};
/*--------------------------------------------------------------------------*/
/**
* Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
* callback when finished. The `onComplete` callback is invoked with one
* argument; (outputSource).
*
* @param {Array|String} [source=''] The source to minify or array of commands.
* -o, --output - Write output to a given path/filename.
* -s, --silent - Skip status updates normally logged to the console.
* -t, --template - Applies template specific minifier options.
*
* @param {Object} [options={}] The options object.
* outputPath - Write output to a given path/filename.
* isSilent - Skip status updates normally logged to the console.
* isTemplate - Applies template specific minifier options.
* onComplete - The function called once minification has finished.
*/
function minify(source, options) {
// used to specify the source map URL
var sourceMapURL;
// used to specify the default minifer modes
var modes = ['simple', 'advanced', 'hybrid'];
source || (source = '');
options || (options = {});
// juggle arguments
if (Array.isArray(source)) {
// convert commands to an options object
options = source;
// used to report invalid command-line arguments
var invalidArgs = _.reject(options.slice(reNode.test(options[0]) ? 2 : 0), function(value, index, options) {
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
/^modes=.*$/.test(value)) {
return true;
}
var result = [
'-o', '--output',
'-p', '--source-map',
'-s', '--silent',
'-t', '--template'
].indexOf(value) > -1;
if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
result = true;
sourceMapURL = value;
}
return result;
});
// report invalid arguments
if (invalidArgs.length) {
console.log(
'\n' +
'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
' passed: ' + invalidArgs.join(', ')
);
return;
}
var filePath = options[options.length - 1],
isMapped = _.contains(options, '-p') || _.contains(options, '--source-map'),
isSilent = _.contains(options, '-s') || _.contains(options, '--silent'),
isTemplate = _.contains(options, '-t') || _.contains(options, '--template'),
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
modes = options.reduce(function(result, value) {
var match = value.match(/modes=(.*)$/);
return match ? match[1].split(/, */) : result;
}, modes);
outputPath = options.reduce(function(result, value, index) {
if (/-o|--output/.test(value)) {
result = options[index + 1];
var dirname = path.dirname(result);
fs.mkdirpSync(dirname);
result = path.join(fs.realpathSync(dirname), path.basename(result));
}
return result;
}, outputPath);
options = {
'filePath': filePath,
'isMapped': isMapped,
'isSilent': isSilent,
'isTemplate': isTemplate,
'modes': modes,
'outputPath': outputPath,
'sourceMapURL': sourceMapURL
};
source = fs.readFileSync(filePath, 'utf8');
}
modes = options.modes || modes;
if (options.isMapped) {
modes = modes.filter(function(mode) {
return mode != 'hybrid';
});
}
if (options.isTemplate) {
modes = modes.filter(function(mode) {
return mode != 'advanced';
});
}
options.modes = modes;
// fetch the Closure Compiler
getDependency({
'id': 'closure-compiler',
'hashId': closureId,
'path': vendorPath,
'title': 'the Closure Compiler',
'onComplete': function(exception) {
var error = exception;
// fetch UglifyJS
getDependency({
'id': 'uglifyjs',
'hashId': uglifyId,
'title': 'UglifyJS',
'path': vendorPath,
'onComplete': function(exception) {
error || (error = exception);
if (!error) {
new Minify(source, options);
}
}
});
}
});
}
/**
* The Minify constructor used to keep state of each `minify` invocation.
*
* @private
* @constructor
* @param {String} source The source to minify.
* @param {Object} options The options object.
* outputPath - Write output to a given path/filename.
* isSilent - Skip status updates normally logged to the console.
* isTemplate - Applies template specific minifier options.
* onComplete - The function called once minification has finished.
*/
function Minify(source, options) {
// juggle arguments
if (typeof source == 'object' && source) {
options = source || options;
source = options.source || '';
}
this.compiled = { 'simple': {}, 'advanced': {} };
this.hybrid = { 'simple': {}, 'advanced': {} };
this.uglified = {};
this.filePath = options.filePath;
this.isMapped = !!options.isMapped;
this.isSilent = !!options.isSilent;
this.isTemplate = !!options.isTemplate;
this.outputPath = options.outputPath;
this.sourceMapURL = options.sourceMapURL;
var modes = this.modes = options.modes;
source = this.source = preprocess(source, options);
this.onComplete = options.onComplete || function(data) {
var outputPath = this.outputPath,
sourceMap = data.sourceMap;
fs.writeFileSync(outputPath, data.source, 'utf8');
if (sourceMap) {
fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
}
};
// begin the minification process
if (_.contains(modes, 'simple')) {
closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
} else if (_.contains(modes, 'advanced')) {
onClosureSimpleGzip.call(this);
} else {
onClosureAdvancedGzip.call(this);
}
}
/*--------------------------------------------------------------------------*/
/**
* Fetches a required `.tar.gz` dependency with the given Git object ID from
* the Lo-Dash repo on GitHub. The object ID may be obtained by running
* `git hash-object path/to/dependency.tar.gz`.
*
* @private
* @param {Object} options The options object.
* id - The Git object ID of the `.tar.gz` file.
* onComplete - The function called once the extraction has finished.
* path - The path of the extraction directory.
* title - The dependency's title used in status updates logged to the console.
*/
function getDependency(options) {
options || (options = {});
var ran,
destPath = options.path,
hashId = options.hashId,
id = options.id,
onComplete = options.onComplete,
title = options.title;
// exit early if dependency exists
if (fs.existsSync(path.join(destPath, id))) {
onComplete();
return;
}
var callback = function(exception) {
if (ran) {
return;
}
if (exception) {
console.error([
'There was a problem installing ' + title + '.',
'Try running the command as root, via `sudo`, or manually install by running:',
'',
"curl -H 'Accept: " + mediaType + "' " + location.href + '/' + hashId + " | tar xvz -C '" + destPath + "'",
''
].join('\n'));
}
ran = true;
process.removeListener('uncaughtException', callback);
onComplete(exception);
};
console.log('Downloading ' + title + '...');
process.on('uncaughtException', callback);
https.get({
'host': location.host,
'path': location.pathname + '/' + hashId,
'headers': {
// By default, all GitHub blob API endpoints return a JSON document
// containing Base64-encoded blob data. Overriding the `Accept` header
// with the GitHub raw media type returns the blob data directly.
// See http://developer.github.com/v3/media/.
'Accept': mediaType,
// As of 2013-04-24, the GitHub API mandates the `User-Agent` header
// for all requests.
'User-Agent': 'Lo-Dash/' + _.VERSION
}
}, function(response) {
var decompressor = zlib.createUnzip(),
parser = new tar.Extract({ 'path': destPath });
parser.on('end', callback);
response.pipe(decompressor).pipe(parser);
});
}
/**
* Retrieves the Java command-line options used for faster minification by
* the Closure Compiler, invoking the `callback` when finished. Subsequent
* calls will lazily return the previously retrieved options. The `callback`
* is invoked with one argument; (options).
*
* See https://code.google.com/p/closure-compiler/wiki/FAQ#What_are_the_recommended_Java_VM_command-line_options?.
*
* @private
* @param {Function} callback The function called once the options have been retrieved.
*/
function getJavaOptions(callback) {
var result = [];
cp.exec('java -version -client -d32', function(error) {
if (!error && process.platform != 'win32') {
result.push('-client', '-d32');
}
getJavaOptions = function(callback) {
_.defer(callback, result);
};
callback(result);
});
}
/**
* Resolves the source map path from the given output path.
*
* @private
* @param {String} outputPath The output path.
* @returns {String} Returns the source map path.
*/
function getMapPath(outputPath) {
return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
}
/*--------------------------------------------------------------------------*/
/**
* Compresses a `source` string using the Closure Compiler. Yields the
* minified result, and any exceptions encountered, to a `callback` function.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {String} mode The optimization mode.
* @param {Function} callback The function called once the process has completed.
*/
function closureCompile(source, mode, callback) {
var filePath = this.filePath,
isAdvanced = mode == 'advanced',
isMapped = this.isMapped,
isSilent = this.isSilent,
isTemplate = this.isTemplate,
options = closureOptions.slice(),
outputPath = this.outputPath,
mapPath = getMapPath(outputPath),
sourceMapURL = this.sourceMapURL || path.basename(mapPath);
// remove copyright header to make other modifications easier
var license = (/^(?:\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*/.exec(source) || [''])[0];
if (license) {
source = source.replace(license, '');
}
var hasIIFE = /^;?\(function[^{]+{/.test(source),
isStrict = hasIIFE && /^;?\(function[^{]+{\s*["']use strict["']/.test(source);
// to avoid stripping the IIFE, convert it to a function call
if (hasIIFE && isAdvanced) {
source = source
.replace(/\(function/, '__iife__$&')
.replace(/\(this\)\)([\s;]*(\n\/\/.+)?)$/, ', this)$1');
}
options.push('--compilation_level=' + optimizationModes[mode]);
if (isMapped) {
options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
}
if (isTemplate) {
options.push('--charset=UTF-8');
}
getJavaOptions(function(javaOptions) {
var compiler = cp.spawn('java', javaOptions.concat('-jar', closurePath, options));
if (!isSilent) {
console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
}
var error = '';
compiler.stderr.on('data', function(data) {
error += data;
});
var output = '';
compiler.stdout.on('data', function(data) {
output += data;
});
compiler.on('exit', function(status) {
// `status` contains the process exit code
if (status) {
var exception = new Error(error);
exception.status = status;
}
// restore IIFE and move exposed vars inside the IIFE
if (hasIIFE && isAdvanced) {
output = output
.replace(/__iife__\(/, '(')
.replace(/,\s*this\)([\s;]*(\n\/\/.+)?)$/, '(this))$1')
.replace(/^((?:var (?:\w+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^{]+{)/, '$2$1');
}
// inject "use strict" directive
if (isStrict) {
output = output.replace(/^[\s\S]*?function[^{]+{/, '$&"use strict";');
}
// restore copyright header
if (license) {
output = license + output;
}
if (isMapped) {
var mapOutput = fs.readFileSync(mapPath, 'utf8');
fs.unlinkSync(mapPath);
output = output.replace(/[\s;]*$/, '\n/*\n//@ sourceMappingURL=' + sourceMapURL) + '\n*/';
mapOutput = JSON.parse(mapOutput);
mapOutput.file = path.basename(outputPath);
mapOutput.sources = [path.basename(filePath)];
mapOutput = JSON.stringify(mapOutput, null, 2);
}
callback(exception, output, mapOutput);
});
// proxy the standard input to the Closure Compiler
compiler.stdin.end(source);
});
}
/**
* Compresses a `source` string using UglifyJS. Yields the result to a
* `callback` function. This function is synchronous; the `callback` is used
* for symmetry.
*
* @private
* @param {String} source The JavaScript source to minify.
* @param {String} label The label to log.
* @param {Function} callback The function called once the process has completed.
*/
function uglify(source, label, callback) {
if (!this.isSilent) {
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...');
}
try {
var uglifyJS = require(uglifyPath);
// 1. parse
var toplevel = uglifyJS.parse(source);
// 2. compress
// enable unsafe comparisons
toplevel.figure_out_scope();
toplevel = toplevel.transform(uglifyJS.Compressor({
'comparisons': false,
'unsafe': true,
'unsafe_comps': true,
'warnings': false
}));
// 3. mangle
// excluding the `define` function exposed by AMD loaders
toplevel.figure_out_scope();
toplevel.compute_char_frequency();
toplevel.mangle_names({
'except': ['define']
});
// 4. output
// restrict lines to 500 characters for consistency with the Closure Compiler
var stream = uglifyJS.OutputStream({
'ascii_only': !this.isTemplate,
'comments': /@cc_on|@license|@preserve/i,
'max_line_len': 500,
});
toplevel.print(stream);
}
catch(e) {
var exception = e;
}
callback(exception, stream && String(stream));
}
/*--------------------------------------------------------------------------*/
/**
* The Closure Compiler callback for simple optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
* @param {String} map The source map output.
*/
function onClosureSimpleCompile(exception, result, map) {
if (exception) {
throw exception;
}
result = postprocess(result);
var simple = this.compiled.simple;
simple.source = result;
simple.sourceMap = map;
zlib.gzip(result, onClosureSimpleGzip.bind(this));
}
/**
* The Closure Compiler `gzip` callback for simple optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onClosureSimpleGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.simple.gzip = result;
}
// compile the source using advanced optimizations
if (_.contains(this.modes, 'advanced')) {
closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
} else {
onClosureAdvancedGzip.call(this);
}
}
/**
* The Closure Compiler callback for advanced optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
* @param {String} map The source map output.
*/
function onClosureAdvancedCompile(exception, result, map) {
if (exception) {
throw exception;
}
result = postprocess(result);
var advanced = this.compiled.advanced;
advanced.source = result;
advanced.sourceMap = map;
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
}
/**
* The Closure Compiler `gzip` callback for advanced optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onClosureAdvancedGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.advanced.gzip = result;
}
// minify the source using UglifyJS
if (!this.isMapped) {
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
} else {
onComplete.call(this);
}
}
/**
* The UglifyJS callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onUglify(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.uglified.source = result;
zlib.gzip(result, onUglifyGzip.bind(this));
}
/**
* The UglifyJS `gzip` callback.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onUglifyGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.uglified.gzip = result;
}
// minify the already Closure Compiler simple optimized source using UglifyJS
var modes = this.modes;
if (_.contains(modes, 'hybrid')) {
if (_.contains(modes, 'simple')) {
uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
} else if (_.contains(modes, 'advanced')) {
onSimpleHybridGzip.call(this);
}
} else {
onComplete.call(this);
}
}
/**
* The hybrid callback for simple optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onSimpleHybrid(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.hybrid.simple.source = result;
zlib.gzip(result, onSimpleHybridGzip.bind(this));
}
/**
* The hybrid `gzip` callback for simple optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onSimpleHybridGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.simple.gzip = result;
}
// minify the already Closure Compiler advance optimized source using UglifyJS
if (_.contains(this.modes, 'advanced')) {
uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
} else {
onComplete.call(this);
}
}
/**
* The hybrid callback for advanced optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source.
*/
function onAdvancedHybrid(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.hybrid.advanced.source = result;
zlib.gzip(result, onAdvancedHybridGzip.bind(this));
}
/**
* The hybrid `gzip` callback for advanced optimizations.
*
* @private
* @param {Object|Undefined} exception The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onAdvancedHybridGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.advanced.gzip = result;
}
// finish by choosing the smallest compressed file
onComplete.call(this);
}
/**
* The callback executed after the source is minified and gzipped.
*
* @private
*/
function onComplete() {
var compiledSimple = this.compiled.simple,
compiledAdvanced = this.compiled.advanced,
uglified = this.uglified,
hybridSimple = this.hybrid.simple,
hybridAdvanced = this.hybrid.advanced;
var objects = [
compiledSimple,
compiledAdvanced,
uglified,
hybridSimple,
hybridAdvanced
];
var gzips = objects
.map(function(data) { return data.gzip; })
.filter(Boolean);
// select the smallest gzipped file and use its minified counterpart as the
// official minified release (ties go to the Closure Compiler)
var min = gzips.reduce(function(min, gzip) {
var length = gzip.length;
return min > length ? length : min;
}, Infinity);
// pass the minified source to the "onComplete" callback
objects.some(function(data) {
var gzip = data.gzip;
if (gzip && gzip.length == min) {
data.outputPath = this.outputPath;
this.onComplete(data);
return true;
}
}, this);
}
/*--------------------------------------------------------------------------*/
// expose `minify`
if (module != require.main) {
module.exports = minify;
}
else {
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node minify.js source.js`) and write to
// `<filename>.min.js`
(function() {
var options = process.argv;
if (options.length < 3) {
return;
}
minify(options);
}());
}
}());

118
build/post-compile.js Normal file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var fs = require('fs'),
vm = require('vm');
/** The minimal license/copyright template */
var licenseTemplate = [
'/**',
' * @license',
' * Lo-Dash <%= VERSION %> lodash.com/license',
' * Underscore.js 1.4.4 underscorejs.org/LICENSE',
' */'
].join('\n');
/*--------------------------------------------------------------------------*/
/**
* Post-process a given minified Lo-Dash `source`, preparing it for
* deployment.
*
* @param {String} source The source to process.
* @returns {String} Returns the processed source.
*/
function postprocess(source) {
// correct overly aggressive Closure Compiler advanced optimization
source = source
.replace(/(document[^&]+&&)\s*(?:\w+|!\d)/, '$1!({toString:0}+"")')
.replace(/"\t"/g, '"\\t"')
.replace(/"[^"]*?\\f[^"]*?"/g,
'" \\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"'
);
try {
var context = vm.createContext({});
vm.runInContext(source, context);
} catch(e) { }
['forEach', 'forIn', 'forOwn'].forEach(function(methodName) {
var pairs = /[!=]==\s*([a-zA-Z]+)(?!\()|([a-zA-Z]+)\s*[!=]==/.exec((context._ || {})[methodName]),
varName = pairs && (pairs[1] || pairs[2]),
value = (value = varName && RegExp('\\b' + varName + '\\s*=\\s*!([01])\\b').exec(source)) && !+value[1];
if (typeof value == 'boolean') {
// replace vars for `false` and `true` with boolean literals
source = source.replace(RegExp('([!=]==\\s*)' + varName + '\\b(?!\\()|\\b' + varName + '(\\s*[!=]==)', 'g'), function(match, prelude, postlude, at) {
// avoid replacing local variables with the same name
return RegExp('\\b' + varName + '\\s*(?:,|=[^=])').test(source.slice(at - 10, at))
? match
: (prelude || '') + value + (postlude || '');
});
}
});
// replace `!1` and `!0` in expressions with `false` and `true` values
[/([!=]==)\s*!1\b|(.)!1\s*([!=]==)/g, /([!=]==)\s*!0\b|(.)!0\s*([!=]==)/g].forEach(function(regexp, index) {
source = source.replace(regexp, function(match, prelude, chr, postlude) {
return (prelude || chr + (/\w/.test(chr) ? ' ' : '')) + !!index + (postlude || '');
});
});
// flip `typeof` expressions to help optimize Safari and
// correct the AMD module definition for AMD build optimizers
// (e.g. from `"number" == typeof x` to `typeof x == "number")
source = source.replace(/(\w)?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.\w]+(?!\[)))/g, function(match, other, type, equality, expression) {
return (other ? other + ' ' : '') + expression + equality + type;
});
// add a space so `define` is detected by the Dojo builder
source = source.replace(/(.)(define\()/, function(match, prelude, define) {
return prelude + (/^\S/.test(prelude) ? ' ' : '') + define;
});
// add trailing semicolon
if (source) {
source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
}
// exit early if version snippet isn't found
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
if (!snippet) {
return source;
}
// remove copyright header
source = source.replace(/^\/\**[\s\S]+?\*\/\n/, '');
// add new copyright header
var version = snippet[2];
source = licenseTemplate.replace('<%= VERSION %>', version) + '\n;' + source;
return source;
}
/*--------------------------------------------------------------------------*/
// expose `postprocess`
if (module != require.main) {
module.exports = postprocess;
}
else {
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
// the same file
(function() {
var options = process.argv;
if (options.length < 3) {
return;
}
var filePath = options[options.length - 1],
source = fs.readFileSync(filePath, 'utf8');
fs.writeFileSync(filePath, postprocess(source), 'utf8');
}());
}
}());

473
build/pre-compile.js Normal file
View File

@@ -0,0 +1,473 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** The Node.js filesystem module */
var fs = require('fs');
/** Used to minify variables embedded in compiled strings */
var compiledVars = [
'args',
'argsIndex',
'argsLength',
'callback',
'className',
'collection',
'conditions',
'ctor',
'errorClass',
'errorProto',
'guard',
'hasOwnProperty',
'index',
'isArguments',
'isArray',
'isProto',
'isString',
'iterable',
'length',
'keys',
'lodash',
'nonEnum',
'nonEnumProps',
'object',
'objectProto',
'objectTypes',
'ownIndex',
'ownProps',
'result',
'skipErrorProps',
'skipProto',
'source',
'stringClass',
'stringProto',
'thisArg',
'toString'
];
/** Used to minify `iteratorTemplate` data properties */
var iteratorOptions = [
'args',
'array',
'bottom',
'firstArg',
'init',
'loop',
'shadowedProps',
'top',
'useHas',
'useKeys'
];
/** Used to minify variables and string values to a single character */
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
minNames.push.apply(minNames, minNames.map(function(value) {
return value + value;
}));
/** Used to protect the specified properties from getting minified */
var propWhitelist = [
'Array',
'Boolean',
'Date',
'Error',
'Function',
'Math',
'Number',
'Object',
'RegExp',
'String',
'TypeError',
'VERSION',
'_',
'__wrapped__',
'after',
'all',
'amd',
'any',
'argsClass',
'argsObject',
'array',
'assign',
'at',
'attachEvent',
'bind',
'bindAll',
'bindKey',
'cache',
'clearTimeout',
'clone',
'cloneDeep',
'collect',
'compact',
'compose',
'contains',
'countBy',
'createCallback',
'criteria',
'debounce',
'defaults',
'defer',
'delay',
'detect',
'difference',
'drop',
'each',
'enumErrorProps',
'enumPrototypes',
'environment',
'escape',
'evaluate',
'every',
'exports',
'extend',
'fastBind',
'fastKeys',
'filter',
'find',
'findIndex',
'findKey',
'first',
'flatten',
'foldl',
'foldr',
'forEach',
'forIn',
'forOwn',
'function',
'functions',
'global',
'groupBy',
'has',
'head',
'identity',
'imports',
'include',
'index',
'indexOf',
'initial',
'inject',
'interpolate',
'intersection',
'invert',
'invoke',
'isArguments',
'isArray',
'isBoolean',
'isDate',
'isElement',
'isEmpty',
'isEqual',
'isEqual',
'isFinite',
'isFinite',
'isFunction',
'isNaN',
'isNull',
'isNumber',
'isObject',
'isPlainObject',
'isRegExp',
'isString',
'isUndefined',
'keys',
'last',
'lastIndexOf',
'leading',
'map',
'max',
'maxWait',
'memoize',
'merge',
'methods',
'min',
'mixin',
'noConflict',
'nodeClass',
'nonEnumArgs',
'nonEnumShadows',
'null',
'number',
'object',
'omit',
'once',
'ownLast',
'pairs',
'parseInt',
'partial',
'partialRight',
'pick',
'pluck',
'random',
'range',
'reduce',
'reduceRight',
'reject',
'rest',
'result',
'runInContext',
'select',
'setImmediate',
'setTimeout',
'shuffle',
'size',
'some',
'sortBy',
'sortedIndex',
'source',
'spliceObjects',
'string',
'support',
'tail',
'take',
'tap',
'template',
'templateSettings',
'throttle',
'times',
'toArray',
'trailing',
'transform',
'undefined',
'unescape',
'unindexedChars',
'union',
'uniq',
'unique',
'uniqueId',
'unzip',
'value',
'values',
'variable',
'where',
'window',
'without',
'wrap',
'zip',
'zipObject',
// properties used by the `backbone` and `underscore` builds
'__chain__',
'chain',
'findWhere'
];
/*--------------------------------------------------------------------------*/
/**
* Pre-process a given Lo-Dash `source`, preparing it for minification.
*
* @param {String} [source=''] The source to process.
* @param {Object} [options={}] The options object.
* @returns {String} Returns the processed source.
*/
function preprocess(source, options) {
source || (source = '');
options || (options = {});
// remove unrecognized JSDoc tags so the Closure Compiler won't complain
source = source.replace(/@(?:alias|category)\b.*/g, '');
if (options.isTemplate) {
return source;
}
// add brackets to whitelisted properties so the Closure Compiler won't mung them
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), function(match, prop) {
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
});
// remove brackets from `lodash.createCallback` in `eachIteratorOptions`
source = source.replace('lodash[\'createCallback\'](callback, thisArg)"', 'lodash.createCallback(callback, thisArg)"');
// remove brackets from `lodash.createCallback` in `_.assign`
source = source.replace("' var callback = lodash['createCallback']", "'var callback=lodash.createCallback");
// remove brackets from `_.escape` in `_.template`
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
// remove brackets from `collection.indexOf` in `_.contains`
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
// remove brackets from `result[length].value` in `_.sortBy`
source = source.replace("result[length]['value']", 'result[length].value');
// remove whitespace from string literals
source = source.replace(/^((?:[ "'\w]+:)? *)"[^"\\\n]*(?:\\.[^"\\\n]*)*"|'[^'\\\n]*(?:\\.[^'\\\n]*)*'/gm, function(string, left) {
// clip after an object literal property name or leading spaces
if (left) {
string = string.slice(left.length);
}
// avoids removing the '\n' of the `stringEscapes` object
string = string.replace(/\[object |delete |else (?!{)|function | in | instanceof |return\s+[\w"']|throw |typeof |use strict|var |@ |(["'])\\n\1|\\\\n|\\n|\s+/g, function(match) {
return match == false || match == '\\n' ? '' : match;
});
// unclip
return (left || '') + string;
});
// remove whitespace from `_.template` related regexes
source = source.replace(/reEmptyString\w+ *=.+/g, function(match) {
return match.replace(/ |\\n/g, '');
});
// remove newline from double-quoted strings in `_.template`
source = source
.replace('"__p += \'"', '"__p+=\'"')
.replace('"\';\n"', '"\';"')
// remove debug sourceURL use in `_.template`
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
// minify internal properties
(function() {
var methods = [
'cacheIndexOf',
'cachePush',
'compareAscending',
'createCache',
'getObject',
'releaseObject',
'sortBy',
'uniq'
];
var props = [
'cache',
'criteria',
'index',
'value'
];
var snippets = source.match(RegExp('^( *)(?:var|function) +(?:' + methods.join('|') + ')\\b[\\s\\S]+?\\n\\1}', 'gm'));
if (!snippets) {
return;
}
snippets.forEach(function(snippet) {
var modified = snippet;
// minify properties
props.forEach(function(prop, index) {
// use minified names different than those chosen for `iteratorOptions`
var minName = minNames[iteratorOptions.length + index],
reBracketProp = RegExp("\\['(" + prop + ")'\\]", 'g'),
reDotProp = RegExp('\\.' + prop + '\\b', 'g'),
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + prop + "\\2 *:", 'g');
modified = modified
.replace(reBracketProp, "['" + minName + "']")
.replace(reDotProp, "['" + minName + "']")
.replace(rePropColon, "$1'" + minName + "':");
});
// replace with modified snippet
source = source.replace(snippet, function() {
return modified;
});
});
}());
// minify all compilable snippets
var snippets = source.match(
RegExp([
// match the `iteratorTemplate`
'^( *)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
// match methods created by `createIterator` calls
'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]*?\\);\\n',
// match variables storing `createIterator` options
'^( *)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
// match `cachePush`, `createCache`, `createIterator`, `getObject`, `releaseObject`, and `uniq` functions
'^( *)(?:var|function) +(?:cachePush|createCache|createIterator|getObject|releaseObject|uniq)\\b[\\s\\S]+?\\n\\3}'
].join('|'), 'gm')
);
// exit early if no compilable snippets
if (!snippets) {
return source;
}
snippets.forEach(function(snippet, index) {
var isFunc = /\bfunction *[ \w]*\(/.test(snippet),
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
modified = snippet;
// add brackets to iterator option properties so the Closure Compiler won't mung them
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), function(match, prop) {
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
});
// remove unnecessary semicolons in strings
modified = modified.replace(/;(?:}["']|(?:\\n|\s)*["']\s*\+\s*["'](?:\\n|\s)*})/g, function(match) {
return match.slice(1);
});
// minify `createIterator` option property names
iteratorOptions.forEach(function(property, index) {
var minName = minNames[index];
// minify variables in `iteratorTemplate` or property names in everything else
modified = isIteratorTemplate
? modified.replace(RegExp('\\b' + property + '\\b', 'g'), minName)
: modified.replace(RegExp("'" + property + "'", 'g'), "'" + minName + "'");
});
// minify snippet variables / arguments
compiledVars.forEach(function(varName, index) {
var minName = minNames[index];
// minify variable names present in strings
if (isFunc && !isIteratorTemplate) {
modified = modified.replace(RegExp('((["\'])[^\\n\\2]*?)\\b' + varName + '\\b(?=[^\\n\\2]*\\2[ ,+;]+$)', 'gm'), function(match, prelude) {
return prelude + minName;
});
}
// ensure properties in compiled strings aren't minified
else {
modified = modified.replace(RegExp('([^.])\\b' + varName + '\\b(?!\' *[\\]:])', 'g'), function(match, prelude) {
return prelude + minName;
});
}
// correct `typeof` string values
if (/^(?:boolean|function|object|number|string|undefined)$/.test(varName)) {
modified = modified.replace(RegExp('(= *)(["\'])' + minName + '\\2|(["\'])' + minName + '\\3( *=)', 'g'), function(match, prelude, preQuote, postQuote, postlude) {
return prelude
? prelude + preQuote + varName + preQuote
: postQuote + varName + postQuote + postlude;
});
}
});
// replace with modified snippet
source = source.replace(snippet, function() {
return modified;
});
});
return source;
}
/*--------------------------------------------------------------------------*/
// expose `preprocess`
if (module != require.main) {
module.exports = preprocess;
}
else {
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
// the same file
(function() {
var options = process.argv;
if (options.length < 3) {
return;
}
var filePath = options[options.length - 1],
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
source = fs.readFileSync(filePath, 'utf8');
fs.writeFileSync(filePath, preprocess(source, {
'isTemplate': isTemplate
}), 'utf8');
}());
}
}());

98
build/util.js Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var fs = require('fs'),
path = require('path');
/** Load other modules */
var _ = require('../lodash.js');
/** Used to indicate if running in Windows */
var isWindows = process.platform == 'win32';
/*--------------------------------------------------------------------------*/
/**
* The path separator.
*
* @memberOf util.path
* @type String
*/
var sep = path.sep || (isWindows ? '\\' : '/');
/**
* The escaped path separator used for inclusion in RegExp strings.
*
* @memberOf util.path
* @type String
*/
var sepEscaped = sep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
/** Used to determine if a path is prefixed with a drive letter, dot, or slash */
var rePrefixed = RegExp('^(?:' + (isWindows ? '[a-zA-Z]:|' : '') + '\\.?)' + sepEscaped);
/*--------------------------------------------------------------------------*/
/**
* Makes the given `dirname` directory, without throwing errors for existing
* directories and making parent directories as needed.
*
* @memberOf util.fs
* @param {String} dirname The path of the directory.
* @param {Number|String} [mode='0777'] The permission mode.
*/
function mkdirpSync(dirname, mode) {
// ensure relative paths are prefixed with `./`
if (!rePrefixed.test(dirname)) {
dirname = '.' + sep + dirname;
}
dirname.split(sep).reduce(function(currPath, segment) {
currPath += sep + segment;
try {
currPath = fs.realpathSync(currPath);
} catch(e) {
fs.mkdirSync(currPath, mode);
}
return currPath;
});
}
/*--------------------------------------------------------------------------*/
/**
* The utility object.
*
* @type Object
*/
var util = {
/**
* The file system object.
*
* @memberOf util
* @type Object
*/
'fs': _.defaults(_.cloneDeep(fs), {
'existsSync': fs.existsSync || path.existsSync,
'mkdirpSync': mkdirpSync
}),
/**
* The path object.
*
* @memberOf util
* @type Object
*/
'path': _.defaults(_.cloneDeep(path), {
'sep': sep,
'sepEscaped': sepEscaped
})
};
/*--------------------------------------------------------------------------*/
// expose
module.exports = util;
}());

View File

@@ -1,12 +1,20 @@
{
"name": "lodash",
"repo": "lodash/lodash",
"version": "2.3.0",
"description": "A utility library delivering consistency, customization, performance, & extras.",
"repo": "bestiejs/lodash",
"version": "1.3.0",
"description": "A low-level utility library delivering consistency, customization, performance, and extra features.",
"license": "MIT",
"keywords": ["amd", "browser", "client", "functional", "server", "util"],
"scripts": [
"index.js",
"dist/lodash.compat.js"
],
"keywords": [
"browser",
"client",
"functional",
"performance",
"server",
"speed",
"util"
]
}

4922
dist/lodash.compat.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +1,51 @@
/**
* @license
* Lo-Dash 2.3.0 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Lo-Dash 1.3.0 (Custom Build) lodash.com/license
* Build: `lodash -o ./dist/lodash.compat.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++e<r;)if(n[e]===t)return e;return-1}function t(t,e){var r=typeof e;if(t=t.l,"boolean"==r||null==e)return t[e]?0:-1;"number"!=r&&"string"!=r&&(r="object");var u="number"==r?e:b+e;return t=(t=t[r])&&t[u],"object"==r?t&&-1<n(t,e)?0:-1:t?0:-1}function e(n){var t=this.l,e=typeof n;if("boolean"==e||null==n)t[n]=true;else{"number"!=e&&"string"!=e&&(e="object");var r="number"==e?n:b+n,t=t[e]||(t[e]={});"object"==e?(t[r]||(t[r]=[])).push(n):t[r]=true
}}function r(n){return n.charCodeAt(0)}function u(n,t){var e=n.m,r=t.m;if(e!==r){if(e>r||typeof e=="undefined")return 1;if(e<r||typeof r=="undefined")return-1}return n.n-t.n}function o(n){var t=-1,r=n.length,u=n[0],o=n[r/2|0],a=n[r-1];if(u&&typeof u=="object"&&o&&typeof o=="object"&&a&&typeof a=="object")return false;for(u=l(),u["false"]=u["null"]=u["true"]=u.undefined=false,o=l(),o.k=n,o.l=u,o.push=e;++t<r;)o.push(n[t]);return o}function a(n){return"\\"+Y[n]}function i(){return v.pop()||[]}function l(){return y.pop()||{k:null,l:null,m:null,"false":false,n:0,"null":false,number:null,object:null,push:null,string:null,"true":false,undefined:false,o:null}
}function f(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function c(n){n.length=0,v.length<w&&v.push(n)}function p(n){var t=n.l;t&&p(t),n.k=n.l=n.m=n.object=n.number=n.string=n.o=null,y.length<w&&y.push(n)}function s(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Array(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function g(e){function v(n){return n&&typeof n=="object"&&!We(n)&&je.call(n,"__wrapped__")?n:new y(n)}function y(n,t){this.__chain__=!!t,this.__wrapped__=n
}function w(n){function t(){if(r){var n=r.slice();Ce.apply(n,arguments)}if(this instanceof t){var o=nt(e.prototype),n=e.apply(o,n||arguments);return Ct(n)?n:o}return e.apply(u,n||arguments)}var e=n[0],r=n[2],u=n[4];return Ke(t,n),t}function Y(n,t,e,r,u){if(e){var o=e(n);if(typeof o!="undefined")return o}if(!Ct(n))return n;var a=ve.call(n);if(!H[a]||!qe.nodeClass&&f(n))return n;var l=Te[a];switch(a){case T:case z:return new l(+n);case W:case M:return new l(n);case J:return o=l(n.source,S.exec(n)),o.lastIndex=n.lastIndex,o
}if(a=We(n),t){var p=!r;r||(r=i()),u||(u=i());for(var g=r.length;g--;)if(r[g]==n)return u[g];o=a?l(n.length):{}}else o=a?s(n):nr({},n);return a&&(je.call(n,"index")&&(o.index=n.index),je.call(n,"input")&&(o.input=n.input)),t?(r.push(n),u.push(o),(a?Ze:rr)(n,function(n,a){o[a]=Y(n,t,e,r,u)}),p&&(c(r),c(u)),o):o}function nt(n){return Ct(n)?Ae(n):{}}function tt(n,t,e){if(typeof n!="function")return Qt;if(typeof t=="undefined"||!("prototype"in n))return n;var r=n.__bindData__;if(typeof r=="undefined"&&(qe.funcNames&&(r=!n.name),r=r||!qe.funcDecomp,!r)){var u=_e.call(n);
qe.funcNames||(r=!I.test(u)),r||(r=B.test(u),Ke(n,r))}if(false===r||true!==r&&1&r[1])return n;switch(e){case 1:return function(e){return n.call(t,e)};case 2:return function(e,r){return n.call(t,e,r)};case 3:return function(e,r,u){return n.call(t,e,r,u)};case 4:return function(e,r,u,o){return n.call(t,e,r,u,o)}}return Ht(n,t)}function ot(n){function t(){var n=l?a:this;if(u){var h=u.slice();Ce.apply(h,arguments)}return(o||c)&&(h||(h=s(arguments)),o&&Ce.apply(h,o),c&&h.length<i)?(r|=16,ot([e,p?r:-4&r,h,null,a,i])):(h||(h=arguments),f&&(e=n[g]),this instanceof t?(n=nt(e.prototype),h=e.apply(n,h),Ct(h)?h:n):e.apply(n,h))
}var e=n[0],r=n[1],u=n[2],o=n[3],a=n[4],i=n[5],l=1&r,f=2&r,c=4&r,p=8&r,g=e;return Ke(t,n),t}function at(e,r){var u=-1,a=yt(),i=e?e.length:0,l=i>=_&&a===n,f=[];if(l){var c=o(r);c?(a=t,r=c):l=false}for(;++u<i;)c=e[u],0>a(r,c)&&f.push(c);return l&&p(r),f}function it(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r<u;){var a=n[r];if(a&&typeof a=="object"&&typeof a.length=="number"&&(We(a)||bt(a))){t||(a=it(a,t,e));var i=-1,l=a.length,f=o.length;for(o.length+=l;++i<l;)o[f++]=a[i]}else e||o.push(a)}return o
}function lt(n,t,e,r,u,o){if(e){var a=e(n,t);if(typeof a!="undefined")return!!a}if(n===t)return 0!==n||1/n==1/t;if(n===n&&!(n&&X[typeof n]||t&&X[typeof t]))return false;if(null==n||null==t)return n===t;var l=ve.call(n),p=ve.call(t);if(l==$&&(l=G),p==$&&(p=G),l!=p)return false;switch(l){case T:case z:return+n==+t;case W:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case J:case M:return n==le(t)}if(p=l==L,!p){var s=je.call(n,"__wrapped__"),g=je.call(t,"__wrapped__");if(s||g)return lt(s?n.__wrapped__:n,g?t.__wrapped__:t,e,r,u,o);
if(l!=G||!qe.nodeClass&&(f(n)||f(t)))return false;if(l=!qe.argsObject&&bt(n)?ae:n.constructor,s=!qe.argsObject&&bt(t)?ae:t.constructor,l!=s&&!(xt(l)&&l instanceof l&&xt(s)&&s instanceof s)&&"constructor"in n&&"constructor"in t)return false}for(s=!u,u||(u=i()),o||(o=i()),l=u.length;l--;)if(u[l]==n)return o[l]==t;var h=0,a=true;if(u.push(n),o.push(t),p){if(l=n.length,h=t.length,a=h==n.length,!a&&!r)return a;for(;h--;)if(p=l,s=t[h],r)for(;p--&&!(a=lt(n[p],s,e,r,u,o)););else if(!(a=lt(n[h],s,e,r,u,o)))break;return a
}return er(t,function(t,i,l){return je.call(l,i)?(h++,a=je.call(n,i)&&lt(n[i],t,e,r,u,o)):void 0}),a&&!r&&er(n,function(n,t,e){return je.call(e,t)?a=-1<--h:void 0}),s&&(c(u),c(o)),a}function ft(n,t,e,r,u){(We(t)?Nt:rr)(t,function(t,o){var a,i,l=t,f=n[o];if(t&&((i=We(t))||ur(t))){for(l=r.length;l--;)if(a=r[l]==t){f=u[l];break}if(!a){var c;e&&(l=e(f,t),c=typeof l!="undefined")&&(f=l),c||(f=i?We(f)?f:[]:ur(f)?f:{}),r.push(t),u.push(f),c||ft(f,t,e,r,u)}}else e&&(l=e(f,t),typeof l=="undefined"&&(l=t)),typeof l!="undefined"&&(f=l);
n[o]=f})}function ct(n,t){return n+be(Le()*(t-n+1))}function pt(e,r,u){var a=-1,l=yt(),f=e?e.length:0,s=[],g=!r&&f>=_&&l===n,h=u||g?i():s;if(g){var v=o(h);v?(l=t,h=v):(g=false,h=u?h:(c(h),s))}for(;++a<f;){var v=e[a],y=u?u(v,a,e):v;(r?!a||h[h.length-1]!==y:0>l(h,y))&&((u||g)&&h.push(y),s.push(v))}return g?(c(h.k),p(h)):u&&c(h),s}function st(n){return function(t,e,r){var u={};if(e=v.createCallback(e,r,3),We(t)){r=-1;for(var o=t.length;++r<o;){var a=t[r];n(u,a,e(a,r,t),t)}}else Ze(t,function(t,r,o){n(u,t,e(t,r,o),o)
});return u}}function gt(n,t,e,r,u,o){var a=1&t,i=4&t,l=16&t,f=32&t;if(!(2&t||xt(n)))throw new fe;l&&!e.length&&(t&=-17,l=e=false),f&&!r.length&&(t&=-33,f=r=false);var c=n&&n.__bindData__;return c&&true!==c?(c=c.slice(),!a||1&c[1]||(c[4]=u),!a&&1&c[1]&&(t|=8),!i||4&c[1]||(c[5]=o),l&&Ce.apply(c[2]||(c[2]=[]),e),f&&Ce.apply(c[3]||(c[3]=[]),r),c[1]|=t,gt.apply(null,c)):(1==t||17===t?w:ot)([n,t,e,r,u,o])}function ht(){Q.h=F,Q.b=Q.c=Q.g=Q.i="",Q.e="t",Q.j=true;for(var n,t=0;n=arguments[t];t++)for(var e in n)Q[e]=n[e];
t=Q.a,Q.d=/^[^,]+/.exec(t)[0],n=re,t="return function("+t+"){",e=Q;var r="var n,t="+e.d+",E="+e.e+";if(!t)return E;"+e.i+";";e.b?(r+="var u=t.length;n=-1;if("+e.b+"){",qe.unindexedChars&&(r+="if(s(t)){t=t.split('')}"),r+="while(++n<u){"+e.g+";}}else{"):qe.nonEnumArgs&&(r+="var u=t.length;n=-1;if(u&&p(t)){while(++n<u){n+='';"+e.g+";}}else{"),qe.enumPrototypes&&(r+="var G=typeof t=='function';"),qe.enumErrorProps&&(r+="var F=t===k||t instanceof Error;");var u=[];if(qe.enumPrototypes&&u.push('!(G&&n=="prototype")'),qe.enumErrorProps&&u.push('!(F&&(n=="message"||n=="name"))'),e.j&&e.f)r+="var C=-1,D=B[typeof t]&&v(t),u=D?D.length:0;while(++C<u){n=D[C];",u.length&&(r+="if("+u.join("&&")+"){"),r+=e.g+";",u.length&&(r+="}"),r+="}";
else if(r+="for(n in t){",e.j&&u.push("m.call(t, n)"),u.length&&(r+="if("+u.join("&&")+"){"),r+=e.g+";",u.length&&(r+="}"),r+="}",qe.nonEnumShadows){for(r+="if(t!==A){var i=t.constructor,r=t===(i&&i.prototype),f=t===J?I:t===k?j:L.call(t),x=y[f];",k=0;7>k;k++)r+="n='"+e.h[k]+"';if((!(r&&x[n])&&m.call(t,n))",e.j||(r+="||(!x[n]&&t[n]!==A[n])"),r+="){"+e.g+"}";r+="}"}return(e.b||qe.nonEnumArgs)&&(r+="}"),r+=e.c+";return E",n("d,j,k,m,o,p,q,s,v,A,B,y,I,J,L",t+r+"}")(tt,q,pe,je,d,bt,We,Et,Q.f,se,X,ze,M,ge,ve)
}function vt(n){return Ve[n]}function yt(){var t=(t=v.indexOf)===qt?n:t;return t}function mt(n){var t,e;return!n||ve.call(n)!=G||(t=n.constructor,xt(t)&&!(t instanceof t))||!qe.argsClass&&bt(n)||!qe.nodeClass&&f(n)?false:qe.ownLast?(er(n,function(n,t,r){return e=je.call(r,t),false}),false!==e):(er(n,function(n,t){e=t}),typeof e=="undefined"||je.call(n,e))}function dt(n){return Qe[n]}function bt(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ve.call(n)==$||false}function _t(n,t,e){var r=Je(n),u=r.length;
for(t=tt(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function wt(n){var t=[];return er(n,function(n,e){xt(n)&&t.push(e)}),t.sort()}function jt(n){for(var t=-1,e=Je(n),r=e.length,u={};++t<r;){var o=e[t];u[n[o]]=o}return u}function xt(n){return typeof n=="function"}function Ct(n){return!(!n||!X[typeof n])}function kt(n){return typeof n=="number"||n&&typeof n=="object"&&ve.call(n)==W||false}function Et(n){return typeof n=="string"||n&&typeof n=="object"&&ve.call(n)==M||false}function Ot(n){for(var t=-1,e=Je(n),r=e.length,u=ne(r);++t<r;)u[t]=n[e[t]];
return u}function St(n,t,e){var r=-1,u=yt(),o=n?n.length:0,a=false;return e=(0>e?Re(0,o+e):e)||0,We(n)?a=-1<u(n,t,e):typeof o=="number"?a=-1<(Et(n)?n.indexOf(t,e):u(n,t,e)):Ze(n,function(n){return++r<e?void 0:!(a=n===t)}),a}function It(n,t,e){var r=true;if(t=v.createCallback(t,e,3),We(n)){e=-1;for(var u=n.length;++e<u&&(r=!!t(n[e],e,n)););}else Ze(n,function(n,e,u){return r=!!t(n,e,u)});return r}function At(n,t,e){var r=[];if(t=v.createCallback(t,e,3),We(n)){e=-1;for(var u=n.length;++e<u;){var o=n[e];
t(o,e,n)&&r.push(o)}}else Ze(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function Dt(n,t,e){if(t=v.createCallback(t,e,3),!We(n)){var r;return Ze(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0}),r}e=-1;for(var u=n.length;++e<u;){var o=n[e];if(t(o,e,n))return o}}function Nt(n,t,e){if(t&&typeof e=="undefined"&&We(n)){e=-1;for(var r=n.length;++e<r&&false!==t(n[e],e,n););}else Ze(n,t,e);return n}function Bt(n,t,e){var r=n,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:tt(t,e,3),We(n))for(;u--&&false!==t(n[u],u,n););else{if(typeof u!="number")var o=Je(n),u=o.length;
else qe.unindexedChars&&Et(n)&&(r=n.split(""));Ze(n,function(n,e,a){return e=o?o[--u]:--u,t(r[e],e,a)})}return n}function Pt(n,t,e){var r=-1,u=n?n.length:0,o=ne(typeof u=="number"?u:0);if(t=v.createCallback(t,e,3),We(n))for(;++r<u;)o[r]=t(n[r],r,n);else Ze(n,function(n,e,u){o[++r]=t(n,e,u)});return o}function Rt(n,t,e){var u=-1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&We(n)){e=-1;for(var a=n.length;++e<a;){var i=n[e];i>o&&(o=i)}}else t=null==t&&Et(n)?r:v.createCallback(t,e,3),Ze(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)
});return o}function Ft(n,t,e,r){var u=3>arguments.length;if(t=v.createCallback(t,r,4),We(n)){var o=-1,a=n.length;for(u&&(e=n[++o]);++o<a;)e=t(e,n[o],o,n)}else Ze(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)});return e}function $t(n,t,e,r){var u=3>arguments.length;return t=v.createCallback(t,r,4),Bt(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Lt(n){var t=-1,e=n?n.length:0,r=ne(typeof e=="number"?e:0);return Nt(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function Tt(n,t,e){var r;if(t=v.createCallback(t,e,3),We(n)){e=-1;
for(var u=n.length;++e<u&&!(r=t(n[e],e,n)););}else Ze(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function zt(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;for(t=v.createCallback(t,e,3);++o<u&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[0]:h;return s(n,0,Fe(Re(0,r),u))}function qt(t,e,r){if(typeof r=="number"){var u=t?t.length:0;r=0>r?Re(0,u+r):r||0}else if(r)return r=Wt(t,e),t[r]===e?r:-1;return n(t,e,r)}function Kt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;
for(t=v.createCallback(t,e,3);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:Re(0,t);return s(n,r)}function Wt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?v.createCallback(e,r,1):Qt,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;return u}function Gt(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(e=v.createCallback(e,r,3)),pt(n,t,e)}function Jt(){for(var n=1<arguments.length?arguments:arguments[0],t=-1,e=n?Rt(lr(n,"length")):0,r=ne(0>e?0:e);++t<e;)r[t]=lr(n,t);
return r}function Mt(n,t){for(var e=-1,r=n?n.length:0,u={};++e<r;){var o=n[e];t?u[o]=t[e]:o&&(u[o[0]]=o[1])}return u}function Ht(n,t){return 2<arguments.length?gt(n,17,s(arguments,2),null,t):gt(n,1,null,null,t)}function Ut(n,t,e){var r,u,o,a,i,l,f,c=0,p=false,s=true;if(!xt(n))throw new fe;if(t=Re(0,t)||0,true===e)var g=true,s=false;else Ct(e)&&(g=e.leading,p="maxWait"in e&&(Re(t,e.maxWait)||0),s="trailing"in e?e.trailing:s);var v=function(){var e=t-(xe()-a);0<e?l=Ee(v,e):(u&&de(u),e=f,u=l=f=h,e&&(c=xe(),o=n.apply(i,r),l||u||(r=i=null)))
},y=function(){l&&de(l),u=l=f=h,(s||p!==t)&&(c=xe(),o=n.apply(i,r),l||u||(r=i=null))};return function(){if(r=arguments,a=xe(),i=this,f=s&&(l||!g),false===p)var e=g&&!l;else{u||g||(c=a);var h=p-(a-c),m=0>=h;m?(u&&(u=de(u)),c=a,o=n.apply(i,r)):u||(u=Ee(y,h))}return m&&l?l=de(l):l||t===p||(l=Ee(v,t)),e&&(m=true,o=n.apply(i,r)),!m||l||u||(r=i=null),o}}function Vt(n){if(!xt(n))throw new fe;var t=s(arguments,1);return Ee(function(){n.apply(h,t)},1)}function Qt(n){return n}function Xt(n,t){var e=n,r=!t||xt(e);
t||(e=y,t=n,n=v),Nt(wt(t),function(u){var o=n[u]=t[u];r&&(e.prototype[u]=function(){var t=this.__wrapped__,r=[t];return Ce.apply(r,arguments),r=o.apply(n,r),t&&typeof t=="object"&&t===r?this:(r=new e(r),r.__chain__=this.__chain__,r)})})}function Yt(){}function Zt(){return this.__wrapped__}e=e?ut.defaults(Z.Object(),e,ut.pick(Z,R)):Z;var ne=e.Array,te=e.Boolean,ee=e.Date,re=e.Function,ue=e.Math,oe=e.Number,ae=e.Object,ie=e.RegExp,le=e.String,fe=e.TypeError,ce=[],pe=e.Error.prototype,se=ae.prototype,ge=le.prototype,he=e._,ve=se.toString,ye=ie("^"+le(ve).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),me=ue.ceil,de=e.clearTimeout,be=ue.floor,_e=re.prototype.toString,we=ye.test(we=ae.getPrototypeOf)&&we,je=se.hasOwnProperty,xe=ye.test(xe=ee.now)&&xe||function(){return+new ee
},Ce=ce.push,ke=se.propertyIsEnumerable,Ee=e.setTimeout,Oe=ce.splice,Se=typeof(Se=rt&&et&&rt.setImmediate)=="function"&&!ye.test(Se)&&Se,Ie=function(){try{var n={},t=ye.test(t=ae.defineProperty)&&t,e=t(n,n,n)&&t}catch(r){}return e}(),Ae=ye.test(Ae=ae.create)&&Ae,De=ye.test(De=ne.isArray)&&De,Ne=e.isFinite,Be=e.isNaN,Pe=ye.test(Pe=ae.keys)&&Pe,Re=ue.max,Fe=ue.min,$e=e.parseInt,Le=ue.random,Te={};Te[L]=ne,Te[T]=te,Te[z]=ee,Te[K]=re,Te[G]=ae,Te[W]=oe,Te[J]=ie,Te[M]=le;var ze={};ze[L]=ze[z]=ze[W]={constructor:true,toLocaleString:true,toString:true,valueOf:true},ze[T]=ze[M]={constructor:true,toString:true,valueOf:true},ze[q]=ze[K]=ze[J]={constructor:true,toString:true},ze[G]={constructor:true},function(){for(var n=F.length;n--;){var t,e=F[n];
for(t in ze)je.call(ze,t)&&!je.call(ze[t],e)&&(ze[t][e]=false)}}(),y.prototype=v.prototype;var qe=v.support={};!function(){var n=function(){this.x=1},t={0:1,length:1},r=[];n.prototype={valueOf:1,y:1};for(var u in new n)r.push(u);for(u in arguments);qe.argsClass=ve.call(arguments)==$,qe.argsObject=arguments.constructor==ae&&!(arguments instanceof ne),qe.enumErrorProps=ke.call(pe,"message")||ke.call(pe,"name"),qe.enumPrototypes=ke.call(n,"prototype"),qe.funcDecomp=!ye.test(e.WinRTError)&&B.test(g),qe.funcNames=typeof re.name=="string",qe.nonEnumArgs=0!=u,qe.nonEnumShadows=!/valueOf/.test(r),qe.ownLast="x"!=r[0],qe.spliceObjects=(ce.splice.call(t,0,1),!t[0]),qe.unindexedChars="xx"!="x"[0]+ae("x")[0];
try{qe.nodeClass=!(ve.call(document)==G&&!({toString:0}+""))}catch(o){qe.nodeClass=true}}(1),v.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:A,variable:"",imports:{_:v}},Ae||(nt=function(){function n(){}return function(t){if(Ct(t)){n.prototype=t;var r=new n;n.prototype=null}return r||e.Object()}}());var Ke=Ie?function(n,t){V.value=t,Ie(n,"__bindData__",V)}:Yt;qe.argsClass||(bt=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&je.call(n,"callee")&&!ke.call(n,"callee")||false
});var We=De||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ve.call(n)==L||false},Ge=ht({a:"z",e:"[]",i:"if(!(B[typeof z]))return E",g:"E.push(n)"}),Je=Pe?function(n){return Ct(n)?qe.enumPrototypes&&typeof n=="function"||qe.nonEnumArgs&&n.length&&bt(n)?Ge(n):Pe(n):[]}:Ge,Me={a:"g,e,K",i:"e=e&&typeof K=='undefined'?e:d(e,K,3)",b:"typeof u=='number'",v:Je,g:"if(e(t[n],n,g)===false)return E"},He={a:"z,H,l",i:"var a=arguments,b=0,c=typeof l=='number'?2:a.length;while(++b<c){t=a[b];if(t&&B[typeof t]){",v:Je,g:"if(typeof E[n]=='undefined')E[n]=t[n]",c:"}}"},Ue={i:"if(!B[typeof t])return E;"+Me.i,b:false},Ve={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Qe=jt(Ve),Xe=ie("("+Je(Qe).join("|")+")","g"),Ye=ie("["+Je(Ve).join("")+"]","g"),Ze=ht(Me),nr=ht(He,{i:He.i.replace(";",";if(c>3&&typeof a[c-2]=='function'){var e=d(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){e=a[--c]}"),g:"E[n]=e?e(E[n],t[n]):t[n]"}),tr=ht(He),er=ht(Me,Ue,{j:false}),rr=ht(Me,Ue);
xt(/x/)&&(xt=function(n){return typeof n=="function"&&ve.call(n)==K});var ur=we?function(n){if(!n||ve.call(n)!=G||!qe.argsClass&&bt(n))return false;var t=n.valueOf,e=typeof t=="function"&&(e=we(t))&&we(e);return e?n==e||we(n)==e:mt(n)}:mt,or=st(function(n,t,e){je.call(n,e)?n[e]++:n[e]=1}),ar=st(function(n,t,e){(je.call(n,e)?n[e]:n[e]=[]).push(t)}),ir=st(function(n,t,e){n[e]=t}),lr=Pt;Se&&(Vt=function(n){if(!xt(n))throw new fe;return Se.apply(e,arguments)});var fr=8==$e(j+"08")?$e:function(n,t){return $e(Et(n)?n.replace(D,""):n,t||0)
};return v.after=function(n,t){if(!xt(t))throw new fe;return function(){return 1>--n?t.apply(this,arguments):void 0}},v.assign=nr,v.at=function(n){var t=arguments,e=-1,r=it(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=ne(t);for(qe.unindexedChars&&Et(n)&&(n=n.split(""));++e<t;)u[e]=n[r[e]];return u},v.bind=Ht,v.bindAll=function(n){for(var t=1<arguments.length?it(arguments,true,false,1):wt(n),e=-1,r=t.length;++e<r;){var u=t[e];n[u]=gt(n[u],1,null,null,n)}return n},v.bindKey=function(n,t){return 2<arguments.length?gt(t,19,s(arguments,2),null,n):gt(t,3,null,null,n)
},v.chain=function(n){return n=new y(n),n.__chain__=true,n},v.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},v.compose=function(){for(var n=arguments,t=n.length;t--;)if(!xt(n[t]))throw new fe;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]}},v.countBy=or,v.create=function(n,t){var e=nt(n);return t?nr(e,t):e},v.createCallback=function(n,t,e){var r=typeof n;if(null==n||"function"==r)return tt(n,t,e);if("object"!=r)return function(t){return t[n]
};var u=Je(n),o=u[0],a=n[o];return 1!=u.length||a!==a||Ct(a)?function(t){for(var e=u.length,r=false;e--&&(r=lt(t[u[e]],n[u[e]],null,true)););return r}:function(n){return n=n[o],a===n&&(0!==a||1/a==1/n)}},v.curry=function(n,t){return t=typeof t=="number"?t:+t||n.length,gt(n,4,null,null,null,t)},v.debounce=Ut,v.defaults=tr,v.defer=Vt,v.delay=function(n,t){if(!xt(n))throw new fe;var e=s(arguments,2);return Ee(function(){n.apply(h,e)},t)},v.difference=function(n){return at(n,it(arguments,true,true,1))},v.filter=At,v.flatten=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(n=Pt(n,e,r)),it(n,t)
},v.forEach=Nt,v.forEachRight=Bt,v.forIn=er,v.forInRight=function(n,t,e){var r=[];er(n,function(n,t){r.push(t,n)});var u=r.length;for(t=tt(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},v.forOwn=rr,v.forOwnRight=_t,v.functions=wt,v.groupBy=ar,v.indexBy=ir,v.initial=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return s(n,0,Fe(Re(0,u-r),u))},v.intersection=function(e){for(var r=arguments,u=r.length,a=-1,l=i(),f=-1,s=yt(),g=e?e.length:0,h=[],v=i();++a<u;){var y=r[a];
l[a]=s===n&&(y?y.length:0)>=_&&o(a?r[a]:v)}n:for(;++f<g;){var m=l[0],y=e[f];if(0>(m?t(m,y):s(v,y))){for(a=u,(m||v).push(y);--a;)if(m=l[a],0>(m?t(m,y):s(r[a],y)))continue n;h.push(y)}}for(;u--;)(m=l[u])&&p(m);return c(l),c(v),h},v.invert=jt,v.invoke=function(n,t){var e=s(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,a=ne(typeof o=="number"?o:0);return Nt(n,function(n){a[++r]=(u?t:n[t]).apply(n,e)}),a},v.keys=Je,v.map=Pt,v.max=Rt,v.memoize=function(n,t){if(!xt(n))throw new fe;var e=function(){var r=e.cache,u=t?t.apply(this,arguments):b+arguments[0];
return je.call(r,u)?r[u]:r[u]=n.apply(this,arguments)};return e.cache={},e},v.merge=function(n){var t=arguments,e=2;if(!Ct(n))return n;if("number"!=typeof t[2]&&(e=t.length),3<e&&"function"==typeof t[e-2])var r=tt(t[--e-1],t[e--],2);else 2<e&&"function"==typeof t[e-1]&&(r=t[--e]);for(var t=s(arguments,1,e),u=-1,o=i(),a=i();++u<e;)ft(n,t[u],r,o,a);return c(o),c(a),n},v.min=function(n,t,e){var u=1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&We(n)){e=-1;for(var a=n.length;++e<a;){var i=n[e];
i<o&&(o=i)}}else t=null==t&&Et(n)?r:v.createCallback(t,e,3),Ze(n,function(n,e,r){e=t(n,e,r),e<u&&(u=e,o=n)});return o},v.omit=function(n,t,e){var r={};if(typeof t!="function"){var u=[];er(n,function(n,t){u.push(t)});for(var u=at(u,it(arguments,true,false,1)),o=-1,a=u.length;++o<a;){var i=u[o];r[i]=n[i]}}else t=v.createCallback(t,e,3),er(n,function(n,e,u){t(n,e,u)||(r[e]=n)});return r},v.once=function(n){var t,e;if(!xt(n))throw new fe;return function(){return t?e:(t=true,e=n.apply(this,arguments),n=null,e)
}},v.pairs=function(n){for(var t=-1,e=Je(n),r=e.length,u=ne(r);++t<r;){var o=e[t];u[t]=[o,n[o]]}return u},v.partial=function(n){return gt(n,16,s(arguments,1))},v.partialRight=function(n){return gt(n,32,null,s(arguments,1))},v.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=-1,o=it(arguments,true,false,1),a=Ct(n)?o.length:0;++u<a;){var i=o[u];i in n&&(r[i]=n[i])}else t=v.createCallback(t,e,3),er(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},v.pluck=lr,v.pull=function(n){for(var t=arguments,e=0,r=t.length,u=n?n.length:0;++e<r;)for(var o=-1,a=t[e];++o<u;)n[o]===a&&(Oe.call(n,o--,1),u--);
return n},v.range=function(n,t,e){n=+n||0,e=typeof e=="number"?e:+e||1,null==t&&(t=n,n=0);var r=-1;t=Re(0,me((t-n)/(e||1)));for(var u=ne(t);++r<t;)u[r]=n,n+=e;return u},v.reject=function(n,t,e){return t=v.createCallback(t,e,3),At(n,function(n,e,r){return!t(n,e,r)})},v.remove=function(n,t,e){var r=-1,u=n?n.length:0,o=[];for(t=v.createCallback(t,e,3);++r<u;)e=n[r],t(e,r,n)&&(o.push(e),Oe.call(n,r--,1),u--);return o},v.rest=Kt,v.shuffle=Lt,v.sortBy=function(n,t,e){var r=-1,o=n?n.length:0,a=ne(typeof o=="number"?o:0);
for(t=v.createCallback(t,e,3),Nt(n,function(n,e,u){var o=a[++r]=l();o.m=t(n,e,u),o.n=r,o.o=n}),o=a.length,a.sort(u);o--;)n=a[o],a[o]=n.o,p(n);return a},v.tap=function(n,t){return t(n),n},v.throttle=function(n,t,e){var r=true,u=true;if(!xt(n))throw new fe;return false===e?r=false:Ct(e)&&(r="leading"in e?e.leading:r,u="trailing"in e?e.trailing:u),U.leading=r,U.maxWait=t,U.trailing=u,Ut(n,t,U)},v.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=ne(n);for(t=tt(t,e,1);++r<n;)u[r]=t(r);return u},v.toArray=function(n){return n&&typeof n.length=="number"?qe.unindexedChars&&Et(n)?n.split(""):s(n):Ot(n)
},v.transform=function(n,t,e,r){var u=We(n);if(null==e)if(u)e=[];else{var o=n&&n.constructor;e=nt(o&&o.prototype)}return t&&(t=v.createCallback(t,r,4),(u?Ze:rr)(n,function(n,r,u){return t(e,n,r,u)})),e},v.union=function(){return pt(it(arguments,true,true))},v.uniq=Gt,v.values=Ot,v.where=At,v.without=function(n){return at(n,s(arguments,1))},v.wrap=function(n,t){return gt(t,16,[n])},v.zip=Jt,v.zipObject=Mt,v.collect=Pt,v.drop=Kt,v.each=Nt,v.eachRight=Bt,v.extend=nr,v.methods=wt,v.object=Mt,v.select=At,v.tail=Kt,v.unique=Gt,v.unzip=Jt,Xt(v),v.clone=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=t,t=false),Y(n,t,typeof e=="function"&&tt(e,r,1))
},v.cloneDeep=function(n,t,e){return Y(n,true,typeof t=="function"&&tt(t,e,1))},v.contains=St,v.escape=function(n){return null==n?"":le(n).replace(Ye,vt)},v.every=It,v.find=Dt,v.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=v.createCallback(t,e,3);++r<u;)if(t(n[r],r,n))return r;return-1},v.findKey=function(n,t,e){var r;return t=v.createCallback(t,e,3),rr(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},v.findLast=function(n,t,e){var r;return t=v.createCallback(t,e,3),Bt(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0
}),r},v.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=v.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},v.findLastKey=function(n,t,e){var r;return t=v.createCallback(t,e,3),_t(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},v.has=function(n,t){return n?je.call(n,t):false},v.identity=Qt,v.indexOf=qt,v.isArguments=bt,v.isArray=We,v.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ve.call(n)==T||false},v.isDate=function(n){return n&&typeof n=="object"&&ve.call(n)==z||false
},v.isElement=function(n){return n&&1===n.nodeType||false},v.isEmpty=function(n){var t=true;if(!n)return t;var e=ve.call(n),r=n.length;return e==L||e==M||(qe.argsClass?e==$:bt(n))||e==G&&typeof r=="number"&&xt(n.splice)?!r:(rr(n,function(){return t=false}),t)},v.isEqual=function(n,t,e,r){return lt(n,t,typeof e=="function"&&tt(e,r,2))},v.isFinite=function(n){return Ne(n)&&!Be(parseFloat(n))},v.isFunction=xt,v.isNaN=function(n){return kt(n)&&n!=+n},v.isNull=function(n){return null===n},v.isNumber=kt,v.isObject=Ct,v.isPlainObject=ur,v.isRegExp=function(n){return n&&X[typeof n]&&ve.call(n)==J||false
},v.isString=Et,v.isUndefined=function(n){return typeof n=="undefined"},v.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?Re(0,r+e):Fe(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},v.mixin=Xt,v.noConflict=function(){return e._=he,this},v.noop=Yt,v.parseInt=fr,v.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Le(),Fe(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t)
},v.reduce=Ft,v.reduceRight=$t,v.result=function(n,t){if(n){var e=n[t];return xt(e)?n[t]():e}},v.runInContext=g,v.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Je(n).length},v.some=Tt,v.sortedIndex=Wt,v.template=function(n,t,e){var r=v.templateSettings;n=le(n||""),e=tr({},e,r);var u,o=tr({},e.imports,r.imports),r=Je(o),o=Ot(o),i=0,l=e.interpolate||N,f="__p+='",l=ie((e.escape||N).source+"|"+l.source+"|"+(l===A?O:N).source+"|"+(e.evaluate||N).source+"|$","g");n.replace(l,function(t,e,r,o,l,c){return r||(r=o),f+=n.slice(i,c).replace(P,a),e&&(f+="'+__e("+e+")+'"),l&&(u=true,f+="';"+l+";\n__p+='"),r&&(f+="'+((__t=("+r+"))==null?'':__t)+'"),i=c+t.length,t
}),f+="';",l=e=e.variable,l||(e="obj",f="with("+e+"){"+f+"}"),f=(u?f.replace(x,""):f).replace(C,"$1").replace(E,"$1;"),f="function("+e+"){"+(l?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+f+"return __p}";try{var c=re(r,"return "+f).apply(h,o)}catch(p){throw p.source=f,p}return t?c(t):(c.source=f,c)},v.unescape=function(n){return null==n?"":le(n).replace(Xe,dt)},v.uniqueId=function(n){var t=++m;return le(null==n?"":n)+t
},v.all=It,v.any=Tt,v.detect=Dt,v.findWhere=Dt,v.foldl=Ft,v.foldr=$t,v.include=St,v.inject=Ft,rr(v,function(n,t){v.prototype[t]||(v.prototype[t]=function(){var t=[this.__wrapped__],e=this.__chain__;return Ce.apply(t,arguments),t=n.apply(v,t),e?new y(t,e):t})}),v.first=zt,v.last=function(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=u;for(t=v.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:h;return s(n,Re(0,u-r))},v.sample=function(n,t,e){return n&&typeof n.length!="number"?n=Ot(n):qe.unindexedChars&&Et(n)&&(n=n.split("")),null==t||e?n?n[ct(0,n.length-1)]:h:(n=Lt(n),n.length=Fe(Re(0,t),n.length),n)
},v.take=zt,v.head=zt,rr(v,function(n,t){var e="sample"!==t;v.prototype[t]||(v.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new y(o,u):o})}),v.VERSION="2.3.0",v.prototype.chain=function(){return this.__chain__=true,this},v.prototype.toString=function(){return le(this.__wrapped__)},v.prototype.value=Zt,v.prototype.valueOf=Zt,Ze(["join","pop","shift"],function(n){var t=ce[n];v.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);
return n?new y(e,n):e}}),Ze(["push","reverse","sort","unshift"],function(n){var t=ce[n];v.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Ze(["concat","slice","splice"],function(n){var t=ce[n];v.prototype[n]=function(){return new y(t.apply(this.__wrapped__,arguments),this.__chain__)}}),qe.spliceObjects||Ze(["pop","shift","splice"],function(n){var t=ce[n],e="splice"==n;v.prototype[n]=function(){var n=this.__chain__,r=this.__wrapped__,u=t.apply(r,arguments);return 0===r.length&&delete r[0],n||e?new y(u,n):u
}}),v}var h,v=[],y=[],m=0,d={},b=+new Date+"",_=75,w=40,j=" \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",x=/\b__p\+='';/g,C=/\b(__p\+=)''\+/g,E=/(__e\(.*?\)|\b__t\))\+'';/g,O=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,S=/\w*$/,I=/^\s*function[ \n\r\t]+\w/,A=/<%=([\s\S]+?)%>/g,D=RegExp("^["+j+"]*0+(?=.$)"),N=/($^)/,B=/\bthis\b/,P=/['\n\r\t\u2028\u2029\\]/g,R="Array Boolean Date Error Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),F="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),$="[object Arguments]",L="[object Array]",T="[object Boolean]",z="[object Date]",q="[object Error]",K="[object Function]",W="[object Number]",G="[object Object]",J="[object RegExp]",M="[object String]",H={};
H[K]=false,H[$]=H[L]=H[T]=H[z]=H[W]=H[G]=H[J]=H[M]=true;var U={leading:false,maxWait:0,trailing:false},V={configurable:false,enumerable:false,value:null,writable:false},Q={a:"",b:null,c:"",d:"",e:"",v:null,g:"",h:null,support:null,i:"",j:false},X={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},Y={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},Z=X[typeof window]&&window||this,nt=X[typeof exports]&&exports&&!exports.nodeType&&exports,tt=X[typeof module]&&module&&!module.nodeType&&module,et=tt&&tt.exports===nt&&nt,rt=X[typeof global]&&global;
!rt||rt.global!==rt&&rt.window!==rt||(Z=rt);var ut=g();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Z._=ut, define(function(){return ut})):nt&&tt?et?(tt.exports=ut)._=ut:nt._=ut:Z._=ut}).call(this);
;!function(n){function t(n,t,r){r=(r||0)-1;for(var e=n.length;++r<e;)if(n[r]===t)return r;return-1}function r(n,r){var e=typeof r;if(n=n.k,"boolean"==e||r==d)return n[r];"number"!=e&&"string"!=e&&(e="object");var u="number"==e?r:x+r;return n=n[e]||(n[e]={}),"object"==e?n[u]&&-1<t(n[u],r)?0:-1:n[u]?0:-1}function e(n){var t=this.k,r=typeof n;if("boolean"==r||n==d)t[n]=y;else{"number"!=r&&"string"!=r&&(r="object");var e="number"==r?n:x+n,u=t[r]||(t[r]={});"object"==r?(u[e]||(u[e]=[])).push(n)==this.b.length&&(t[r]=b):u[e]=y
}}function u(n){return n.charCodeAt(0)}function a(n,t){var r=n.m,e=t.m;if(n=n.l,t=t.l,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1}return r<e?-1:1}function o(n){var t=-1,r=n.length,u=c();u["false"]=u["null"]=u["true"]=u.undefined=b;var a=c();for(a.b=n,a.k=u,a.push=e;++t<r;)a.push(n[t]);return u.object===false?(g(a),d):a}function i(n){return"\\"+tt[n]}function l(){return _.pop()||[]}function c(){return C.pop()||{a:"",b:d,c:"",l:d,"false":b,d:"",m:0,e:"",leading:b,f:"",maxWait:0,"null":b,number:d,object:d,push:d,g:d,string:d,h:"",trailing:b,"true":b,undefined:b,i:b,j:b,n:d}
}function f(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function p(){}function s(n){_.length==E&&(_.length=E-1),n.length=0,_.push(n)}function g(n){var t=n.k;t&&g(t),C.length==E&&(C.length=E-1),n.b=n.k=n.l=n.object=n.number=n.string=n.n=d,C.push(n)}function v(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function h(e){function _(n){return n&&typeof n=="object"&&!qr(n)&&sr.call(n,"__wrapped__")?n:new C(n)
}function C(n){this.__wrapped__=n}function E(n,t,r,e){function u(){var e=arguments,c=o?this:t;return a||(n=t[i]),r.length&&(e=e.length?(e=Sr.call(e),l?e.concat(r):r.concat(e)):r),this instanceof u?(c=rt(n.prototype),e=n.apply(c,e),mt(e)?e:c):n.apply(c,e)}var a=ht(n),o=!r,i=t;if(o){var l=e;r=t}else if(!a){if(!e)throw new Zt;t=n}return u}function tt(){var n=c();n.g=L,n.b=n.c=n.f=n.h="",n.e="r",n.i=y,n.j=!!Rr;for(var t,r=0;t=arguments[r];r++)for(var e in t)n[e]=t[e];r=n.a,n.d=/^[^,]+/.exec(r)[0],t=Mt,r="return function("+r+"){",e="var m,r="+n.d+",C="+n.e+";if(!r)return C;"+n.h+";",n.b?(e+="var s=r.length;m=-1;if("+n.b+"){",Pr.unindexedChars&&(e+="if(q(r)){r=r.split('')}"),e+="while(++m<s){"+n.f+";}}else{"):Pr.nonEnumArgs&&(e+="var s=r.length;m=-1;if(s&&n(r)){while(++m<s){m+='';"+n.f+";}}else{"),Pr.enumPrototypes&&(e+="var E=typeof r=='function';"),Pr.enumErrorProps&&(e+="var D=r===j||r instanceof Error;");
var u=[];if(Pr.enumPrototypes&&u.push('!(E&&m=="prototype")'),Pr.enumErrorProps&&u.push('!(D&&(m=="message"||m=="name"))'),n.i&&n.j)e+="var A=-1,B=z[typeof r]&&t(r),s=B?B.length:0;while(++A<s){m=B[A];",u.length&&(e+="if("+u.join("&&")+"){"),e+=n.f+";",u.length&&(e+="}"),e+="}";else if(e+="for(m in r){",n.i&&u.push("l.call(r, m)"),u.length&&(e+="if("+u.join("&&")+"){"),e+=n.f+";",u.length&&(e+="}"),e+="}",Pr.nonEnumShadows){for(e+="if(r!==y){var h=r.constructor,p=r===(h&&h.prototype),e=r===H?G:r===j?i:J.call(r),v=w[e];",k=0;7>k;k++)e+="m='"+n.g[k]+"';if((!(p&&v[m])&&l.call(r,m))",n.i||(e+="||(!v[m]&&r[m]!==y[m])"),e+="){"+n.f+"}";
e+="}"}return(n.b||Pr.nonEnumArgs)&&(e+="}"),e+=n.c+";return C",t=t("i,j,l,n,o,q,t,u,y,z,w,G,H,J",r+e+"}"),g(n),t(M,tr,sr,ft,qr,dt,Rr,_,rr,nt,Nr,Y,er,yr)}function rt(n){return mt(n)?br(n):{}}function ut(n){return Wr[n]}function ot(){var n=(n=_.indexOf)===Pt?t:n;return n}function it(n){return function(t,r,e,u){return typeof r!="boolean"&&r!=d&&(u=e,e=u&&u[r]===t?m:r,r=b),e!=d&&(e=_.createCallback(e,u)),n(t,r,e,u)}}function lt(n){var t,r;return!n||yr.call(n)!=Q||(t=n.constructor,ht(t)&&!(t instanceof t))||!Pr.argsClass&&ft(n)||!Pr.nodeClass&&f(n)?b:Pr.ownLast?(Jr(n,function(n,t,e){return r=sr.call(e,t),b
}),r!==false):(Jr(n,function(n,t){r=t}),r===m||sr.call(n,r))}function ct(n){return Lr[n]}function ft(n){return yr.call(n)==G}function pt(n,t,r,e,u,a){var o=n;if(typeof t!="boolean"&&t!=d&&(e=r,r=t,t=b),typeof r=="function"){if(r=typeof e=="undefined"?r:_.createCallback(r,e,1),o=r(o),typeof o!="undefined")return o;o=n}if(e=mt(o)){var i=yr.call(o);if(!Z[i]||!Pr.nodeClass&&f(o))return o;var c=qr(o)}if(!e||!t)return e?c?v(o):Gr({},o):o;switch(e=Br[i],i){case J:case K:return new e(+o);case V:case Y:return new e(o);
case X:return e(o.source,P.exec(o))}i=!u,u||(u=l()),a||(a=l());for(var p=u.length;p--;)if(u[p]==n)return a[p];return o=c?e(o.length):{},c&&(sr.call(n,"index")&&(o.index=n.index),sr.call(n,"input")&&(o.input=n.input)),u.push(n),a.push(o),(c?Tr:Kr)(n,function(n,e){o[e]=pt(n,t,r,m,u,a)}),i&&(s(u),s(a)),o}function st(n){var t=[];return Jr(n,function(n,r){ht(n)&&t.push(r)}),t.sort()}function gt(n){for(var t=-1,r=Rr(n),e=r.length,u={};++t<e;){var a=r[t];u[n[a]]=a}return u}function vt(n,t,r,e,u,a){var o=r===w;
if(typeof r=="function"&&!o){r=_.createCallback(r,e,2);var i=r(n,t);if(typeof i!="undefined")return!!i}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,p=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=p&&"object"!=p))return b;if(n==d||t==d)return n===t;if(p=yr.call(n),c=yr.call(t),p==G&&(p=Q),c==G&&(c=Q),p!=c)return b;switch(p){case J:case K:return+n==+t;case V:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case X:case Y:return n==Yt(t)}if(c=p==H,!c){if(sr.call(n,"__wrapped__")||sr.call(t,"__wrapped__"))return vt(n.__wrapped__||n,t.__wrapped__||t,r,e,u,a);
if(p!=Q||!Pr.nodeClass&&(f(n)||f(t)))return b;var p=!Pr.argsObject&&ft(n)?Qt:n.constructor,g=!Pr.argsObject&&ft(t)?Qt:t.constructor;if(p!=g&&(!ht(p)||!(p instanceof p&&ht(g)&&g instanceof g)))return b}for(g=!u,u||(u=l()),a||(a=l()),p=u.length;p--;)if(u[p]==n)return a[p]==t;var v=0,i=y;if(u.push(n),a.push(t),c){if(p=n.length,v=t.length,i=v==n.length,!i&&!o)return i;for(;v--;)if(c=p,g=t[v],o)for(;c--&&!(i=vt(n[c],g,r,e,u,a)););else if(!(i=vt(n[v],g,r,e,u,a)))break;return i}return Jr(t,function(t,o,l){return sr.call(l,o)?(v++,i=sr.call(n,o)&&vt(n[o],t,r,e,u,a)):void 0
}),i&&!o&&Jr(n,function(n,t,r){return sr.call(r,t)?i=-1<--v:void 0}),g&&(s(u),s(a)),i}function ht(n){return typeof n=="function"}function mt(n){return!(!n||!nt[typeof n])}function yt(n){return typeof n=="number"||yr.call(n)==V}function dt(n){return typeof n=="string"||yr.call(n)==Y}function bt(n,t,r){var e=arguments,u=0,a=2;if(!mt(n))return n;if(r===w)var o=e[3],i=e[4],c=e[5];else{var f=y,i=l(),c=l();typeof r!="number"&&(a=e.length),3<a&&"function"==typeof e[a-2]?o=_.createCallback(e[--a-1],e[a--],2):2<a&&"function"==typeof e[a-1]&&(o=e[--a])
}for(;++u<a;)(qr(e[u])?xt:Kr)(e[u],function(t,r){var e,u,a=t,l=n[r];if(t&&((u=qr(t))||Mr(t))){for(a=i.length;a--;)if(e=i[a]==t){l=c[a];break}if(!e){var f;o&&(a=o(l,t),f=typeof a!="undefined")&&(l=a),f||(l=u?qr(l)?l:[]:Mr(l)?l:{}),i.push(t),c.push(l),f||(l=bt(l,t,w,o,i,c))}}else o&&(a=o(l,t),typeof a=="undefined"&&(a=t)),typeof a!="undefined"&&(l=a);n[r]=l});return f&&(s(i),s(c)),n}function _t(n){for(var t=-1,r=Rr(n),e=r.length,u=Ht(e);++t<e;)u[t]=n[r[t]];return u}function Ct(n,t,r){var e=-1,u=ot(),a=n?n.length:0,o=b;
return r=(0>r?kr(0,a+r):r)||0,a&&typeof a=="number"?o=-1<(dt(n)?n.indexOf(t,r):u(n,t,r)):Tr(n,function(n){return++e<r?void 0:!(o=n===t)}),o}function jt(n,t,r){var e=y;if(t=_.createCallback(t,r),qr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else Tr(n,function(n,r,u){return e=!!t(n,r,u)});return e}function wt(n,t,r){var e=[];if(t=_.createCallback(t,r),qr(n)){r=-1;for(var u=n.length;++r<u;){var a=n[r];t(a,r,n)&&e.push(a)}}else Tr(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function kt(n,t,r){if(t=_.createCallback(t,r),!qr(n)){var e;
return Tr(n,function(n,r,u){return t(n,r,u)?(e=n,b):void 0}),e}r=-1;for(var u=n.length;++r<u;){var a=n[r];if(t(a,r,n))return a}}function xt(n,t,r){if(t&&typeof r=="undefined"&&qr(n)){r=-1;for(var e=n.length;++r<e&&t(n[r],r,n)!==false;);}else Tr(n,t,r);return n}function Ot(n,t,r){var e=-1,u=n?n.length:0,a=Ht(typeof u=="number"?u:0);if(t=_.createCallback(t,r),qr(n))for(;++e<u;)a[e]=t(n[e],e,n);else Tr(n,function(n,r,u){a[++e]=t(n,r,u)});return a}function Et(n,t,r){var e=-1/0,a=e;if(!t&&qr(n)){r=-1;for(var o=n.length;++r<o;){var i=n[r];
i>a&&(a=i)}}else t=!t&&dt(n)?u:_.createCallback(t,r),Tr(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,a=n)});return a}function St(n,t,r,e){var u=3>arguments.length;if(t=_.createCallback(t,e,4),qr(n)){var a=-1,o=n.length;for(u&&(r=n[++a]);++a<o;)r=t(r,n[a],a,n)}else Tr(n,function(n,e,a){r=u?(u=b,n):t(r,n,e,a)});return r}function At(n,t,r,e){var u=n,a=n?n.length:0,o=3>arguments.length;if(typeof a!="number")var i=Rr(n),a=i.length;else Pr.unindexedChars&&dt(n)&&(u=n.split(""));return t=_.createCallback(t,e,4),xt(n,function(n,e,l){e=i?i[--a]:--a,r=o?(o=b,u[e]):t(r,u[e],e,l)
}),r}function It(n,t,r){var e;if(t=_.createCallback(t,r),qr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else Tr(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function Bt(n){var e=-1,u=ot(),a=n?n.length:0,i=lr.apply(nr,Sr.call(arguments,1)),l=[],c=a>=O&&u===t;if(c){var f=o(i);f?(u=r,i=f):c=b}for(;++e<a;)f=n[e],0>u(i,f)&&l.push(f);return c&&g(i),l}function Nt(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=d){var a=-1;for(t=_.createCallback(t,r);++a<u&&t(n[a],a,n);)e++}else if(e=t,e==d||r)return n[0];
return v(n,0,xr(kr(0,e),u))}}function Pt(n,r,e){if(typeof e=="number"){var u=n?n.length:0;e=0>e?kr(0,u+e):e||0}else if(e)return e=Ft(n,r),n[e]===r?e:-1;return n?t(n,r,e):-1}function zt(n,t,r){if(typeof t!="number"&&t!=d){var e=0,u=-1,a=n?n.length:0;for(t=_.createCallback(t,r);++u<a&&t(n[u],u,n);)e++}else e=t==d||r?1:kr(0,t);return v(n,e)}function Ft(n,t,r,e){var u=0,a=n?n.length:u;for(r=r?_.createCallback(r,e,1):Wt,t=r(t);u<a;)e=u+a>>>1,r(n[e])<t?u=e+1:a=e;return u}function $t(n){for(var t=-1,r=n?Et(Ur(n,"length")):0,e=Ht(0>r?0:r);++t<r;)e[t]=Ur(n,t);
return e}function qt(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var a=n[r];t?u[a]=t[r]:u[a[0]]=a[1]}return u}function Dt(n,t){return Pr.fastBind||dr&&2<arguments.length?dr.call.apply(dr,arguments):E(n,t,Sr.call(arguments,2))}function Rt(n,t,r){function e(){ir(s),ir(g),c=0,s=g=d}function u(){var t=v&&(!h||1<c);e(),t&&(p!==false&&(f=new Kt),i=n.apply(l,o))}function a(){e(),(v||p!==t)&&(f=new Kt,i=n.apply(l,o))}var o,i,l,c=0,f=0,p=b,s=d,g=d,v=y;if(t=kr(0,t||0),r===y)var h=y,v=b;else mt(r)&&(h=r.leading,p="maxWait"in r&&kr(t,r.maxWait||0),v="trailing"in r?r.trailing:v);
return function(){if(o=arguments,l=this,c++,ir(g),p===false)h&&2>c&&(i=n.apply(l,o));else{var r=new Kt;!s&&!h&&(f=r);var e=p-(r-f);0<e?s||(s=mr(a,e)):(ir(s),s=d,f=r,i=n.apply(l,o))}return t!==p&&(g=mr(u,t)),i}}function Tt(n){var t=Sr.call(arguments,1);return mr(function(){n.apply(m,t)},1)}function Wt(n){return n}function Lt(n){xt(st(n),function(t){var r=_[t]=n[t];_.prototype[t]=function(){var n=this.__wrapped__,t=[n];return gr.apply(t,arguments),t=r.apply(_,t),n&&typeof n=="object"&&n===t?this:new C(t)
}})}function Gt(){return this.__wrapped__}e=e?at.defaults(n.Object(),e,at.pick(n,W)):n;var Ht=e.Array,Jt=e.Boolean,Kt=e.Date,Mt=e.Function,Ut=e.Math,Vt=e.Number,Qt=e.Object,Xt=e.RegExp,Yt=e.String,Zt=e.TypeError,nr=[],tr=e.Error.prototype,rr=Qt.prototype,er=Yt.prototype,ur=e._,ar=Xt("^"+Yt(rr.valueOf).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),or=Ut.ceil,ir=e.clearTimeout,lr=nr.concat,cr=Ut.floor,fr=Mt.prototype.toString,pr=ar.test(pr=Qt.getPrototypeOf)&&pr,sr=rr.hasOwnProperty,gr=nr.push,vr=rr.propertyIsEnumerable,hr=e.setImmediate,mr=e.setTimeout,yr=rr.toString,dr=ar.test(dr=yr.bind)&&dr,br=ar.test(br=Qt.create)&&br,_r=ar.test(_r=Ht.isArray)&&_r,Cr=e.isFinite,jr=e.isNaN,wr=ar.test(wr=Qt.keys)&&wr,kr=Ut.max,xr=Ut.min,Or=e.parseInt,Er=Ut.random,Sr=nr.slice,Ar=ar.test(e.attachEvent),Ir=dr&&!/\n|true/.test(dr+Ar),Br={};
Br[H]=Ht,Br[J]=Jt,Br[K]=Kt,Br[U]=Mt,Br[Q]=Qt,Br[V]=Vt,Br[X]=Xt,Br[Y]=Yt;var Nr={};Nr[H]=Nr[K]=Nr[V]={constructor:y,toLocaleString:y,toString:y,valueOf:y},Nr[J]=Nr[Y]={constructor:y,toString:y,valueOf:y},Nr[M]=Nr[U]=Nr[X]={constructor:y,toString:y},Nr[Q]={constructor:y},function(){for(var n=L.length;n--;){var t,r=L[n];for(t in Nr)sr.call(Nr,t)&&!sr.call(Nr[t],r)&&(Nr[t][r]=b)}}(),C.prototype=_.prototype;var Pr=_.support={};!function(){function n(){this.x=1}var t={0:1,length:1},r=[];n.prototype={valueOf:1};
for(var e in new n)r.push(e);for(e in arguments);Pr.argsObject=arguments.constructor==Qt&&!(arguments instanceof Ht),Pr.argsClass=ft(arguments),Pr.enumErrorProps=vr.call(tr,"message")||vr.call(tr,"name"),Pr.enumPrototypes=vr.call(n,"prototype"),Pr.fastBind=dr&&!Ir,Pr.ownLast="x"!=r[0],Pr.nonEnumArgs=0!=e,Pr.nonEnumShadows=!/valueOf/.test(r),Pr.spliceObjects=(nr.splice.call(t,0,1),!t[0]),Pr.unindexedChars="xx"!="x"[0]+Qt("x")[0];try{Pr.nodeClass=!(yr.call(document)==Q&&!({toString:0}+""))}catch(u){Pr.nodeClass=y
}}(1),_.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:z,variable:"",imports:{_:_}};var zr={a:"x,F,k",h:"var a=arguments,b=0,c=typeof k=='number'?2:a.length;while(++b<c){r=a[b];if(r&&z[typeof r]){",f:"if(typeof C[m]=='undefined')C[m]=r[m]",c:"}}"},Fr={a:"f,d,I",h:"d=d&&typeof I=='undefined'?d:u.createCallback(d,I)",b:"typeof s=='number'",f:"if(d(r[m],m,f)===false)return C"},$r={h:"if(!z[typeof r])return C;"+Fr.h,b:b};br||(rt=function(n){if(mt(n)){p.prototype=n;
var t=new p;p.prototype=d}return t||{}}),Pr.argsClass||(ft=function(n){return n?sr.call(n,"callee"):b});var qr=_r||function(n){return n?typeof n=="object"&&yr.call(n)==H:b},Dr=tt({a:"x",e:"[]",h:"if(!(z[typeof x]))return C",f:"C.push(m)"}),Rr=wr?function(n){return mt(n)?Pr.enumPrototypes&&typeof n=="function"||Pr.nonEnumArgs&&n.length&&ft(n)?Dr(n):wr(n):[]}:Dr,Tr=tt(Fr),Wr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Lr=gt(Wr),Gr=tt(zr,{h:zr.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=u.createCallback(a[--c-1],a[c--],2)}else if(c>2&&typeof a[c-1]=='function'){d=a[--c]}"),f:"C[m]=d?d(C[m],r[m]):r[m]"}),Hr=tt(zr),Jr=tt(Fr,$r,{i:b}),Kr=tt(Fr,$r);
ht(/x/)&&(ht=function(n){return typeof n=="function"&&yr.call(n)==U});var Mr=pr?function(n){if(!n||yr.call(n)!=Q||!Pr.argsClass&&ft(n))return b;var t=n.valueOf,r=typeof t=="function"&&(r=pr(t))&&pr(r);return r?n==r||pr(n)==r:lt(n)}:lt,Ur=Ot,Vr=it(function Yr(n,t,r){for(var e=-1,u=n?n.length:0,a=[];++e<u;){var o=n[e];r&&(o=r(o,e,n)),qr(o)?gr.apply(a,t?o:Yr(o)):a.push(o)}return a}),Qr=it(function(n,e,u){var a=-1,i=ot(),c=n?n.length:0,f=[],p=!e&&c>=O&&i===t,v=u||p?l():f;if(p){var h=o(v);h?(i=r,v=h):(p=b,v=u?v:(s(v),f))
}for(;++a<c;){var h=n[a],m=u?u(h,a,n):h;(e?!a||v[v.length-1]!==m:0>i(v,m))&&((u||p)&&v.push(m),f.push(h))}return p?(s(v.b),g(v)):u&&s(v),f});Ir&&et&&typeof hr=="function"&&(Tt=Dt(hr,e));var Xr=8==Or($+"08")?Or:function(n,t){return Or(dt(n)?n.replace(q,""):n,t||0)};return _.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},_.assign=Gr,_.at=function(n){var t=-1,r=lr.apply(nr,Sr.call(arguments,1)),e=r.length,u=Ht(e);for(Pr.unindexedChars&&dt(n)&&(n=n.split(""));++t<e;)u[t]=n[r[t]];
return u},_.bind=Dt,_.bindAll=function(n){for(var t=1<arguments.length?lr.apply(nr,Sr.call(arguments,1)):st(n),r=-1,e=t.length;++r<e;){var u=t[r];n[u]=Dt(n[u],n)}return n},_.bindKey=function(n,t){return E(n,t,Sr.call(arguments,2),w)},_.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},_.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},_.countBy=function(n,t,r){var e={};return t=_.createCallback(t,r),xt(n,function(n,r,u){r=Yt(t(n,r,u)),sr.call(e,r)?e[r]++:e[r]=1
}),e},_.createCallback=function(n,t,r){if(n==d)return Wt;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=Rr(n);return function(t){for(var r=u.length,e=b;r--&&(e=vt(t[u[r]],n[u[r]],w)););return e}}return typeof t=="undefined"||F&&!F.test(fr.call(n))?n:1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,a){return n.call(t,r,e,u,a)}:function(r,e,u){return n.call(t,r,e,u)}},_.debounce=Rt,_.defaults=Hr,_.defer=Tt,_.delay=function(n,t){var r=Sr.call(arguments,2);
return mr(function(){n.apply(m,r)},t)},_.difference=Bt,_.filter=wt,_.flatten=Vr,_.forEach=xt,_.forIn=Jr,_.forOwn=Kr,_.functions=st,_.groupBy=function(n,t,r){var e={};return t=_.createCallback(t,r),xt(n,function(n,r,u){r=Yt(t(n,r,u)),(sr.call(e,r)?e[r]:e[r]=[]).push(n)}),e},_.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=d){var a=u;for(t=_.createCallback(t,r);a--&&t(n[a],a,n);)e++}else e=t==d||r?1:t||e;return v(n,0,xr(kr(0,u-e),u))},_.intersection=function(n){for(var e=arguments,u=e.length,a=-1,i=l(),c=-1,f=ot(),p=n?n.length:0,v=[],h=l();++a<u;){var m=e[a];
i[a]=f===t&&(m?m.length:0)>=O&&o(a?e[a]:h)}n:for(;++c<p;){var y=i[0],m=n[c];if(0>(y?r(y,m):f(h,m))){for(a=u,(y||h).push(m);--a;)if(y=i[a],0>(y?r(y,m):f(e[a],m)))continue n;v.push(m)}}for(;u--;)(y=i[u])&&g(y);return s(i),s(h),v},_.invert=gt,_.invoke=function(n,t){var r=Sr.call(arguments,2),e=-1,u=typeof t=="function",a=n?n.length:0,o=Ht(typeof a=="number"?a:0);return xt(n,function(n){o[++e]=(u?t:n[t]).apply(n,r)}),o},_.keys=Rr,_.map=Ot,_.max=Et,_.memoize=function(n,t){function r(){var e=r.cache,u=x+(t?t.apply(this,arguments):arguments[0]);
return sr.call(e,u)?e[u]:e[u]=n.apply(this,arguments)}return r.cache={},r},_.merge=bt,_.min=function(n,t,r){var e=1/0,a=e;if(!t&&qr(n)){r=-1;for(var o=n.length;++r<o;){var i=n[r];i<a&&(a=i)}}else t=!t&&dt(n)?u:_.createCallback(t,r),Tr(n,function(n,r,u){r=t(n,r,u),r<e&&(e=r,a=n)});return a},_.omit=function(n,t,r){var e=ot(),u=typeof t=="function",a={};if(u)t=_.createCallback(t,r);else var o=lr.apply(nr,Sr.call(arguments,1));return Jr(n,function(n,r,i){(u?!t(n,r,i):0>e(o,r))&&(a[r]=n)}),a},_.once=function(n){var t,r;
return function(){return t?r:(t=y,r=n.apply(this,arguments),n=d,r)}},_.pairs=function(n){for(var t=-1,r=Rr(n),e=r.length,u=Ht(e);++t<e;){var a=r[t];u[t]=[a,n[a]]}return u},_.partial=function(n){return E(n,Sr.call(arguments,1))},_.partialRight=function(n){return E(n,Sr.call(arguments,1),d,w)},_.pick=function(n,t,r){var e={};if(typeof t!="function")for(var u=-1,a=lr.apply(nr,Sr.call(arguments,1)),o=mt(n)?a.length:0;++u<o;){var i=a[u];i in n&&(e[i]=n[i])}else t=_.createCallback(t,r),Jr(n,function(n,r,u){t(n,r,u)&&(e[r]=n)
});return e},_.pluck=Ur,_.range=function(n,t,r){n=+n||0,r=+r||1,t==d&&(t=n,n=0);var e=-1;t=kr(0,or((t-n)/r));for(var u=Ht(t);++e<t;)u[e]=n,n+=r;return u},_.reject=function(n,t,r){return t=_.createCallback(t,r),wt(n,function(n,r,e){return!t(n,r,e)})},_.rest=zt,_.shuffle=function(n){var t=-1,r=n?n.length:0,e=Ht(typeof r=="number"?r:0);return xt(n,function(n){var r=cr(Er()*(++t+1));e[t]=e[r],e[r]=n}),e},_.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,o=Ht(typeof u=="number"?u:0);for(t=_.createCallback(t,r),xt(n,function(n,r,u){var a=o[++e]=c();
a.l=t(n,r,u),a.m=e,a.n=n}),u=o.length,o.sort(a);u--;)n=o[u],o[u]=n.n,g(n);return o},_.tap=function(n,t){return t(n),n},_.throttle=function(n,t,r){var e=y,u=y;return r===false?e=b:mt(r)&&(e="leading"in r?r.leading:e,u="trailing"in r?r.trailing:u),r=c(),r.leading=e,r.maxWait=t,r.trailing=u,n=Rt(n,t,r),g(r),n},_.times=function(n,t,r){n=-1<(n=+n)?n:0;var e=-1,u=Ht(n);for(t=_.createCallback(t,r,1);++e<n;)u[e]=t(e);return u},_.toArray=function(n){return n&&typeof n.length=="number"?Pr.unindexedChars&&dt(n)?n.split(""):v(n):_t(n)
},_.transform=function(n,t,r,e){var u=qr(n);return t=_.createCallback(t,e,4),r==d&&(u?r=[]:(e=n&&n.constructor,r=rt(e&&e.prototype))),(u?Tr:Kr)(n,function(n,e,u){return t(r,n,e,u)}),r},_.union=function(n){return qr(n)||(arguments[0]=n?Sr.call(n):nr),Qr(lr.apply(nr,arguments))},_.uniq=Qr,_.unzip=$t,_.values=_t,_.where=wt,_.without=function(n){return Bt(n,Sr.call(arguments,1))},_.wrap=function(n,t){return function(){var r=[n];return gr.apply(r,arguments),t.apply(this,r)}},_.zip=function(n){return n?$t(arguments):[]
},_.zipObject=qt,_.collect=Ot,_.drop=zt,_.each=xt,_.extend=Gr,_.methods=st,_.object=qt,_.select=wt,_.tail=zt,_.unique=Qr,Lt(_),_.chain=_,_.prototype.chain=function(){return this},_.clone=pt,_.cloneDeep=function(n,t,r){return pt(n,y,t,r)},_.contains=Ct,_.escape=function(n){return n==d?"":Yt(n).replace(R,ut)},_.every=jt,_.find=kt,_.findIndex=function(n,t,r){var e=-1,u=n?n.length:0;for(t=_.createCallback(t,r);++e<u;)if(t(n[e],e,n))return e;return-1},_.findKey=function(n,t,r){var e;return t=_.createCallback(t,r),Kr(n,function(n,r,u){return t(n,r,u)?(e=r,b):void 0
}),e},_.has=function(n,t){return n?sr.call(n,t):b},_.identity=Wt,_.indexOf=Pt,_.isArguments=ft,_.isArray=qr,_.isBoolean=function(n){return n===y||n===false||yr.call(n)==J},_.isDate=function(n){return n?typeof n=="object"&&yr.call(n)==K:b},_.isElement=function(n){return n?1===n.nodeType:b},_.isEmpty=function(n){var t=y;if(!n)return t;var r=yr.call(n),e=n.length;return r==H||r==Y||(Pr.argsClass?r==G:ft(n))||r==Q&&typeof e=="number"&&ht(n.splice)?!e:(Kr(n,function(){return t=b}),t)},_.isEqual=vt,_.isFinite=function(n){return Cr(n)&&!jr(parseFloat(n))
},_.isFunction=ht,_.isNaN=function(n){return yt(n)&&n!=+n},_.isNull=function(n){return n===d},_.isNumber=yt,_.isObject=mt,_.isPlainObject=Mr,_.isRegExp=function(n){return!(!n||!nt[typeof n])&&yr.call(n)==X},_.isString=dt,_.isUndefined=function(n){return typeof n=="undefined"},_.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?kr(0,e+r):xr(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},_.mixin=Lt,_.noConflict=function(){return e._=ur,this},_.parseInt=Xr,_.random=function(n,t){n==d&&t==d&&(t=1),n=+n||0,t==d?(t=n,n=0):t=+t||0;
var r=Er();return n%1||t%1?n+xr(r*(t-n+parseFloat("1e-"+((r+"").length-1))),t):n+cr(r*(t-n+1))},_.reduce=St,_.reduceRight=At,_.result=function(n,t){var r=n?n[t]:m;return ht(r)?n[t]():r},_.runInContext=h,_.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Rr(n).length},_.some=It,_.sortedIndex=Ft,_.template=function(n,t,r){var e=_.templateSettings;n||(n=""),r=Hr({},r,e);var u,a=Hr({},r.imports,e.imports),e=Rr(a),a=_t(a),o=0,l=r.interpolate||D,c="__p+='",l=Xt((r.escape||D).source+"|"+l.source+"|"+(l===z?N:D).source+"|"+(r.evaluate||D).source+"|$","g");
n.replace(l,function(t,r,e,a,l,f){return e||(e=a),c+=n.slice(o,f).replace(T,i),r&&(c+="'+__e("+r+")+'"),l&&(u=y,c+="';"+l+";__p+='"),e&&(c+="'+((__t=("+e+"))==null?'':__t)+'"),o=f+t.length,t}),c+="';\n",l=r=r.variable,l||(r="obj",c="with("+r+"){"+c+"}"),c=(u?c.replace(S,""):c).replace(A,"$1").replace(I,"$1;"),c="function("+r+"){"+(l?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+c+"return __p}";try{var f=Mt(e,"return "+c).apply(m,a)
}catch(p){throw p.source=c,p}return t?f(t):(f.source=c,f)},_.unescape=function(n){return n==d?"":Yt(n).replace(B,ct)},_.uniqueId=function(n){var t=++j;return Yt(n==d?"":n)+t},_.all=jt,_.any=It,_.detect=kt,_.findWhere=kt,_.foldl=St,_.foldr=At,_.include=Ct,_.inject=St,Kr(_,function(n,t){_.prototype[t]||(_.prototype[t]=function(){var t=[this.__wrapped__];return gr.apply(t,arguments),n.apply(_,t)})}),_.first=Nt,_.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=d){var a=u;for(t=_.createCallback(t,r);a--&&t(n[a],a,n);)e++
}else if(e=t,e==d||r)return n[u-1];return v(n,kr(0,u-e))}},_.take=Nt,_.head=Nt,Kr(_,function(n,t){_.prototype[t]||(_.prototype[t]=function(t,r){var e=n(this.__wrapped__,t,r);return t==d||r&&typeof t!="function"?e:new C(e)})}),_.VERSION="1.3.0",_.prototype.toString=function(){return Yt(this.__wrapped__)},_.prototype.value=Gt,_.prototype.valueOf=Gt,Tr(["join","pop","shift"],function(n){var t=nr[n];_.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)}}),Tr(["push","reverse","sort","unshift"],function(n){var t=nr[n];
_.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Tr(["concat","slice","splice"],function(n){var t=nr[n];_.prototype[n]=function(){return new C(t.apply(this.__wrapped__,arguments))}}),Pr.spliceObjects||Tr(["pop","shift","splice"],function(n){var t=nr[n],r="splice"==n;_.prototype[n]=function(){var n=this.__wrapped__,e=t.apply(n,arguments);return 0===n.length&&delete n[0],r?new C(e):e}}),_}var m,y=!0,d=null,b=!1,_=[],C=[],j=0,w={},x=+new Date+"",O=75,E=10,S=/\b__p\+='';/g,A=/\b(__p\+=)''\+/g,I=/(__e\(.*?\)|\b__t\))\+'';/g,B=/&(?:amp|lt|gt|quot|#39);/g,N=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,P=/\w*$/,z=/<%=([\s\S]+?)%>/g,F=(F=/\bthis\b/)&&F.test(h)&&F,$=" \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",q=RegExp("^["+$+"]*0+(?=.$)"),D=/($^)/,R=/[&<>"']/g,T=/['\n\r\t\u2028\u2029\\]/g,W="Array Boolean Date Error Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),L="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),G="[object Arguments]",H="[object Array]",J="[object Boolean]",K="[object Date]",M="[object Error]",U="[object Function]",V="[object Number]",Q="[object Object]",X="[object RegExp]",Y="[object String]",Z={};
Z[U]=b,Z[G]=Z[H]=Z[J]=Z[K]=Z[V]=Z[Q]=Z[X]=Z[Y]=y;var nt={"boolean":b,"function":y,object:y,number:b,string:b,undefined:b},tt={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},rt=nt[typeof exports]&&exports,et=nt[typeof module]&&module&&module.exports==rt&&module,ut=nt[typeof global]&&global;!ut||ut.global!==ut&&ut.window!==ut||(n=ut);var at=h();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=at, define(function(){return at})):rt&&!rt.nodeType?et?(et.exports=at)._=at:rt._=at:n._=at
}(this);

4675
dist/lodash.js vendored

File diff suppressed because it is too large Load Diff

95
dist/lodash.min.js vendored
View File

@@ -1,55 +1,48 @@
/**
* @license
* Lo-Dash 2.3.0 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Lo-Dash 1.3.0 (Custom Build) lodash.com/license
* Build: `lodash modern -o ./dist/lodash.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(){function n(n,t,e){e=(e||0)-1;for(var r=n?n.length:0;++e<r;)if(n[e]===t)return e;return-1}function t(t,e){var r=typeof e;if(t=t.l,"boolean"==r||null==e)return t[e]?0:-1;"number"!=r&&"string"!=r&&(r="object");var u="number"==r?e:m+e;return t=(t=t[r])&&t[u],"object"==r?t&&-1<n(t,e)?0:-1:t?0:-1}function e(n){var t=this.l,e=typeof n;if("boolean"==e||null==n)t[n]=true;else{"number"!=e&&"string"!=e&&(e="object");var r="number"==e?n:m+n,t=t[e]||(t[e]={});"object"==e?(t[r]||(t[r]=[])).push(n):t[r]=true
}}function r(n){return n.charCodeAt(0)}function u(n,t){var e=n.m,r=t.m;if(e!==r){if(e>r||typeof e=="undefined")return 1;if(e<r||typeof r=="undefined")return-1}return n.n-t.n}function o(n){var t=-1,r=n.length,u=n[0],o=n[r/2|0],i=n[r-1];if(u&&typeof u=="object"&&o&&typeof o=="object"&&i&&typeof i=="object")return false;for(u=f(),u["false"]=u["null"]=u["true"]=u.undefined=false,o=f(),o.k=n,o.l=u,o.push=e;++t<r;)o.push(n[t]);return o}function i(n){return"\\"+V[n]}function a(){return h.pop()||[]}function f(){return g.pop()||{k:null,l:null,m:null,"false":false,n:0,"null":false,number:null,object:null,push:null,string:null,"true":false,undefined:false,o:null}
}function l(n){n.length=0,h.length<b&&h.push(n)}function c(n){var t=n.l;t&&c(t),n.k=n.l=n.m=n.object=n.number=n.string=n.o=null,g.length<b&&g.push(n)}function p(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Array(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function s(e){function h(n){if(!n||ve.call(n)!=q)return false;var t=n.valueOf,e=typeof t=="function"&&(e=be(t))&&be(e);return e?n==e||be(n)==e:yt(n)}function g(n,t,e){if(!n||!U[typeof n])return n;t=t&&typeof e=="undefined"?t:ut(t,e,3);
for(var r=-1,u=U[typeof n]&&ze(n),o=u?u.length:0;++r<o&&(e=u[r],false!==t(n[e],e,n)););return n}function b(n,t,e){var r;if(!n||!U[typeof n])return n;t=t&&typeof e=="undefined"?t:ut(t,e,3);for(r in n)if(false===t(n[r],r,n))break;return n}function V(n,t,e){var r,u=n,o=u;if(!u)return o;for(var i=arguments,a=0,f=typeof e=="number"?2:i.length;++a<f;)if((u=i[a])&&U[typeof u])for(var l=-1,c=U[typeof u]&&ze(u),p=c?c.length:0;++l<p;)r=c[l],"undefined"==typeof o[r]&&(o[r]=u[r]);return o}function H(n,t,e){var r,u=n,o=u;
if(!u)return o;var i=arguments,a=0,f=typeof e=="number"?2:i.length;if(3<f&&"function"==typeof i[f-2])var l=ut(i[--f-1],i[f--],2);else 2<f&&"function"==typeof i[f-1]&&(l=i[--f]);for(;++a<f;)if((u=i[a])&&U[typeof u])for(var c=-1,p=U[typeof u]&&ze(u),s=p?p.length:0;++c<s;)r=p[c],o[r]=l?l(o[r],u[r]):u[r];return o}function J(n){var t,e=[];if(!n||!U[typeof n])return e;for(t in n)de.call(n,t)&&e.push(t);return e}function Z(n){return n&&typeof n=="object"&&!qe(n)&&de.call(n,"__wrapped__")?n:new nt(n)}function nt(n,t){this.__chain__=!!t,this.__wrapped__=n
}function tt(n){function t(){if(r){var n=r.slice();je.apply(n,arguments)}if(this instanceof t){var o=rt(e.prototype),n=e.apply(o,n||arguments);return kt(n)?n:o}return e.apply(u,n||arguments)}var e=n[0],r=n[2],u=n[4];return We(t,n),t}function et(n,t,e,r,u){if(e){var o=e(n);if(typeof o!="undefined")return o}if(!kt(n))return n;var i=ve.call(n);if(!K[i])return n;var f=Te[i];switch(i){case F:case T:return new f(+n);case W:case P:return new f(n);case z:return o=f(n.source,C.exec(n)),o.lastIndex=n.lastIndex,o
}if(i=qe(n),t){var c=!r;r||(r=a()),u||(u=a());for(var s=r.length;s--;)if(r[s]==n)return u[s];o=i?f(n.length):{}}else o=i?p(n):H({},n);return i&&(de.call(n,"index")&&(o.index=n.index),de.call(n,"input")&&(o.input=n.input)),t?(r.push(n),u.push(o),(i?Rt:g)(n,function(n,i){o[i]=et(n,t,e,r,u)}),c&&(l(r),l(u)),o):o}function rt(n){return kt(n)?Ie(n):{}}function ut(n,t,e){if(typeof n!="function")return Qt;if(typeof t=="undefined"||!("prototype"in n))return n;var r=n.__bindData__;if(typeof r=="undefined"&&(Be.funcNames&&(r=!n.name),r=r||!Be.funcDecomp,!r)){var u=_e.call(n);
Be.funcNames||(r=!O.test(u)),r||(r=E.test(u),We(n,r))}if(false===r||true!==r&&1&r[1])return n;switch(e){case 1:return function(e){return n.call(t,e)};case 2:return function(e,r){return n.call(t,e,r)};case 3:return function(e,r,u){return n.call(t,e,r,u)};case 4:return function(e,r,u,o){return n.call(t,e,r,u,o)}}return Gt(n,t)}function ot(n){function t(){var n=f?i:this;if(u){var h=u.slice();je.apply(h,arguments)}return(o||c)&&(h||(h=p(arguments)),o&&je.apply(h,o),c&&h.length<a)?(r|=16,ot([e,s?r:-4&r,h,null,i,a])):(h||(h=arguments),l&&(e=n[v]),this instanceof t?(n=rt(e.prototype),h=e.apply(n,h),kt(h)?h:n):e.apply(n,h))
}var e=n[0],r=n[1],u=n[2],o=n[3],i=n[4],a=n[5],f=1&r,l=2&r,c=4&r,s=8&r,v=e;return We(t,n),t}function it(e,r){var u=-1,i=gt(),a=e?e.length:0,f=a>=_&&i===n,l=[];if(f){var p=o(r);p?(i=t,r=p):f=false}for(;++u<a;)p=e[u],0>i(r,p)&&l.push(p);return f&&c(r),l}function at(n,t,e,r){r=(r||0)-1;for(var u=n?n.length:0,o=[];++r<u;){var i=n[r];if(i&&typeof i=="object"&&typeof i.length=="number"&&(qe(i)||_t(i))){t||(i=at(i,t,e));var a=-1,f=i.length,l=o.length;for(o.length+=f;++a<f;)o[l++]=i[a]}else e||o.push(i)}return o
}function ft(n,t,e,r,u,o){if(e){var i=e(n,t);if(typeof i!="undefined")return!!i}if(n===t)return 0!==n||1/n==1/t;if(n===n&&!(n&&U[typeof n]||t&&U[typeof t]))return false;if(null==n||null==t)return n===t;var f=ve.call(n),c=ve.call(t);if(f==D&&(f=q),c==D&&(c=q),f!=c)return false;switch(f){case F:case T:return+n==+t;case W:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case z:case P:return n==fe(t)}if(c=f==$,!c){var p=de.call(n,"__wrapped__"),s=de.call(t,"__wrapped__");if(p||s)return ft(p?n.__wrapped__:n,s?t.__wrapped__:t,e,r,u,o);
if(f!=q)return false;if(f=n.constructor,p=t.constructor,f!=p&&!(jt(f)&&f instanceof f&&jt(p)&&p instanceof p)&&"constructor"in n&&"constructor"in t)return false}for(p=!u,u||(u=a()),o||(o=a()),f=u.length;f--;)if(u[f]==n)return o[f]==t;var v=0,i=true;if(u.push(n),o.push(t),c){if(f=n.length,v=t.length,i=v==n.length,!i&&!r)return i;for(;v--;)if(c=f,p=t[v],r)for(;c--&&!(i=ft(n[c],p,e,r,u,o)););else if(!(i=ft(n[v],p,e,r,u,o)))break;return i}return b(t,function(t,a,f){return de.call(f,a)?(v++,i=de.call(n,a)&&ft(n[a],t,e,r,u,o)):void 0
}),i&&!r&&b(n,function(n,t,e){return de.call(e,t)?i=-1<--v:void 0}),p&&(l(u),l(o)),i}function lt(n,t,e,r,u){(qe(t)?Rt:g)(t,function(t,o){var i,a,f=t,l=n[o];if(t&&((a=qe(t))||h(t))){for(f=r.length;f--;)if(i=r[f]==t){l=u[f];break}if(!i){var c;e&&(f=e(l,t),c=typeof f!="undefined")&&(l=f),c||(l=a?qe(l)?l:[]:h(l)?l:{}),r.push(t),u.push(l),c||lt(l,t,e,r,u)}}else e&&(f=e(l,t),typeof f=="undefined"&&(f=t)),typeof f!="undefined"&&(l=f);n[o]=l})}function ct(n,t){return n+me(Fe()*(t-n+1))}function pt(e,r,u){var i=-1,f=gt(),p=e?e.length:0,s=[],v=!r&&p>=_&&f===n,h=u||v?a():s;
if(v){var g=o(h);g?(f=t,h=g):(v=false,h=u?h:(l(h),s))}for(;++i<p;){var g=e[i],y=u?u(g,i,e):g;(r?!i||h[h.length-1]!==y:0>f(h,y))&&((u||v)&&h.push(y),s.push(g))}return v?(l(h.k),c(h)):u&&l(h),s}function st(n){return function(t,e,r){var u={};e=Z.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r<o;){var i=t[r];n(u,i,e(i,r,t),t)}else g(t,function(t,r,o){n(u,t,e(t,r,o),o)});return u}}function vt(n,t,e,r,u,o){var i=1&t,a=4&t,f=16&t,l=32&t;if(!(2&t||jt(n)))throw new le;f&&!e.length&&(t&=-17,f=e=false),l&&!r.length&&(t&=-33,l=r=false);
var c=n&&n.__bindData__;return c&&true!==c?(c=c.slice(),!i||1&c[1]||(c[4]=u),!i&&1&c[1]&&(t|=8),!a||4&c[1]||(c[5]=o),f&&je.apply(c[2]||(c[2]=[]),e),l&&je.apply(c[3]||(c[3]=[]),r),c[1]|=t,vt.apply(null,c)):(1==t||17===t?tt:ot)([n,t,e,r,u,o])}function ht(n){return Pe[n]}function gt(){var t=(t=Z.indexOf)===Pt?n:t;return t}function yt(n){var t,e;return n&&ve.call(n)==q&&(t=n.constructor,!jt(t)||t instanceof t)?(b(n,function(n,t){e=t}),typeof e=="undefined"||de.call(n,e)):false}function mt(n){return Ke[n]}function _t(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ve.call(n)==D||false
}function bt(n,t,e){var r=ze(n),u=r.length;for(t=ut(t,e,3);u--&&(e=r[u],false!==t(n[e],e,n)););return n}function dt(n){var t=[];return b(n,function(n,e){jt(n)&&t.push(e)}),t.sort()}function wt(n){for(var t=-1,e=ze(n),r=e.length,u={};++t<r;){var o=e[t];u[n[o]]=o}return u}function jt(n){return typeof n=="function"}function kt(n){return!(!n||!U[typeof n])}function xt(n){return typeof n=="number"||n&&typeof n=="object"&&ve.call(n)==W||false}function Ct(n){return typeof n=="string"||n&&typeof n=="object"&&ve.call(n)==P||false
}function Ot(n){for(var t=-1,e=ze(n),r=e.length,u=ne(r);++t<r;)u[t]=n[e[t]];return u}function It(n,t,e){var r=-1,u=gt(),o=n?n.length:0,i=false;return e=(0>e?Ae(0,o+e):e)||0,qe(n)?i=-1<u(n,t,e):typeof o=="number"?i=-1<(Ct(n)?n.indexOf(t,e):u(n,t,e)):g(n,function(n){return++r<e?void 0:!(i=n===t)}),i}function Nt(n,t,e){var r=true;t=Z.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&(r=!!t(n[e],e,n)););else g(n,function(n,e,u){return r=!!t(n,e,u)});return r}function St(n,t,e){var r=[];
t=Z.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u;){var o=n[e];t(o,e,n)&&r.push(o)}else g(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function Et(n,t,e){t=Z.createCallback(t,e,3),e=-1;var r=n?n.length:0;if(typeof r!="number"){var u;return g(n,function(n,e,r){return t(n,e,r)?(u=n,false):void 0}),u}for(;++e<r;){var o=n[e];if(t(o,e,n))return o}}function Rt(n,t,e){var r=-1,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:ut(t,e,3),typeof u=="number")for(;++r<u&&false!==t(n[r],r,n););else g(n,t);
return n}function At(n,t,e){var r=n?n.length:0;if(t=t&&typeof e=="undefined"?t:ut(t,e,3),typeof r=="number")for(;r--&&false!==t(n[r],r,n););else{var u=ze(n),r=u.length;g(n,function(n,e,o){return e=u?u[--r]:--r,t(o[e],e,o)})}return n}function Dt(n,t,e){var r=-1,u=n?n.length:0;if(t=Z.createCallback(t,e,3),typeof u=="number")for(var o=ne(u);++r<u;)o[r]=t(n[r],r,n);else o=[],g(n,function(n,e,u){o[++r]=t(n,e,u)});return o}function $t(n,t,e){var u=-1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&qe(n)){e=-1;
for(var i=n.length;++e<i;){var a=n[e];a>o&&(o=a)}}else t=null==t&&Ct(n)?r:Z.createCallback(t,e,3),Rt(n,function(n,e,r){e=t(n,e,r),e>u&&(u=e,o=n)});return o}function Ft(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number")for(var u=ne(r);++e<r;)u[e]=n[e][t];return u||Dt(n,t)}function Tt(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=Z.createCallback(t,r,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(e=n[++o]);++o<i;)e=t(e,n[o],o,n);else g(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)});return e
}function Bt(n,t,e,r){var u=3>arguments.length;return t=Z.createCallback(t,r,4),At(n,function(n,r,o){e=u?(u=false,n):t(e,n,r,o)}),e}function Wt(n){var t=-1,e=n?n.length:0,r=ne(typeof e=="number"?e:0);return Rt(n,function(n){var e=ct(0,++t);r[t]=r[e],r[e]=n}),r}function qt(n,t,e){var r;t=Z.createCallback(t,e,3),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&!(r=t(n[e],e,n)););else g(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function zt(n,t,e){var r=0,u=n?n.length:0;if(typeof t!="number"&&null!=t){var o=-1;
for(t=Z.createCallback(t,e,3);++o<u&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[0]:v;return p(n,0,De(Ae(0,r),u))}function Pt(t,e,r){if(typeof r=="number"){var u=t?t.length:0;r=0>r?Ae(0,u+r):r||0}else if(r)return r=Lt(t,e),t[r]===e?r:-1;return n(t,e,r)}function Kt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=Z.createCallback(t,e,3);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:Ae(0,t);return p(n,r)}function Lt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?Z.createCallback(e,r,1):Qt,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;
return u}function Mt(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(e=Z.createCallback(e,r,3)),pt(n,t,e)}function Ut(){for(var n=1<arguments.length?arguments:arguments[0],t=-1,e=n?$t(Ft(n,"length")):0,r=ne(0>e?0:e);++t<e;)r[t]=Ft(n,t);return r}function Vt(n,t){for(var e=-1,r=n?n.length:0,u={};++e<r;){var o=n[e];t?u[o]=t[e]:o&&(u[o[0]]=o[1])}return u}function Gt(n,t){return 2<arguments.length?vt(n,17,p(arguments,2),null,t):vt(n,1,null,null,t)
}function Ht(n,t,e){function r(){c&&ye(c),i=c=p=v,(g||h!==t)&&(s=we(),a=n.apply(l,o),c||i||(o=l=null))}function u(){var e=t-(we()-f);0<e?c=ke(u,e):(i&&ye(i),e=p,i=c=p=v,e&&(s=we(),a=n.apply(l,o),c||i||(o=l=null)))}var o,i,a,f,l,c,p,s=0,h=false,g=true;if(!jt(n))throw new le;if(t=Ae(0,t)||0,true===e)var y=true,g=false;else kt(e)&&(y=e.leading,h="maxWait"in e&&(Ae(t,e.maxWait)||0),g="trailing"in e?e.trailing:g);return function(){if(o=arguments,f=we(),l=this,p=g&&(c||!y),false===h)var e=y&&!c;else{i||y||(s=f);var v=h-(f-s),m=0>=v;
m?(i&&(i=ye(i)),s=f,a=n.apply(l,o)):i||(i=ke(r,v))}return m&&c?c=ye(c):c||t===h||(c=ke(u,t)),e&&(m=true,a=n.apply(l,o)),!m||c||i||(o=l=null),a}}function Jt(n){if(!jt(n))throw new le;var t=p(arguments,1);return ke(function(){n.apply(v,t)},1)}function Qt(n){return n}function Xt(n,t){var e=n,r=!t||jt(e);t||(e=nt,t=n,n=Z),Rt(dt(t),function(u){var o=n[u]=t[u];r&&(e.prototype[u]=function(){var t=this.__wrapped__,r=[t];return je.apply(r,arguments),r=o.apply(n,r),t&&typeof t=="object"&&t===r?this:(r=new e(r),r.__chain__=this.__chain__,r)
})})}function Yt(){}function Zt(){return this.__wrapped__}e=e?Y.defaults(G.Object(),e,Y.pick(G,A)):G;var ne=e.Array,te=e.Boolean,ee=e.Date,re=e.Function,ue=e.Math,oe=e.Number,ie=e.Object,ae=e.RegExp,fe=e.String,le=e.TypeError,ce=[],pe=ie.prototype,se=e._,ve=pe.toString,he=ae("^"+fe(ve).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),ge=ue.ceil,ye=e.clearTimeout,me=ue.floor,_e=re.prototype.toString,be=he.test(be=ie.getPrototypeOf)&&be,de=pe.hasOwnProperty,we=he.test(we=ee.now)&&we||function(){return+new ee
},je=ce.push,ke=e.setTimeout,xe=ce.splice,Ce=typeof(Ce=X&&Q&&X.setImmediate)=="function"&&!he.test(Ce)&&Ce,Oe=function(){try{var n={},t=he.test(t=ie.defineProperty)&&t,e=t(n,n,n)&&t}catch(r){}return e}(),Ie=he.test(Ie=ie.create)&&Ie,Ne=he.test(Ne=ne.isArray)&&Ne,Se=e.isFinite,Ee=e.isNaN,Re=he.test(Re=ie.keys)&&Re,Ae=ue.max,De=ue.min,$e=e.parseInt,Fe=ue.random,Te={};Te[$]=ne,Te[F]=te,Te[T]=ee,Te[B]=re,Te[q]=ie,Te[W]=oe,Te[z]=ae,Te[P]=fe,nt.prototype=Z.prototype;var Be=Z.support={};Be.funcDecomp=!he.test(e.a)&&E.test(s),Be.funcNames=typeof re.name=="string",Z.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:I,variable:"",imports:{_:Z}},Ie||(rt=function(){function n(){}return function(t){if(kt(t)){n.prototype=t;
var r=new n;n.prototype=null}return r||e.Object()}}());var We=Oe?function(n,t){M.value=t,Oe(n,"__bindData__",M)}:Yt,qe=Ne||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&ve.call(n)==$||false},ze=Re?function(n){return kt(n)?Re(n):[]}:J,Pe={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Ke=wt(Pe),Le=ae("("+ze(Ke).join("|")+")","g"),Me=ae("["+ze(Pe).join("")+"]","g"),Ue=st(function(n,t,e){de.call(n,e)?n[e]++:n[e]=1}),Ve=st(function(n,t,e){(de.call(n,e)?n[e]:n[e]=[]).push(t)
}),Ge=st(function(n,t,e){n[e]=t});Ce&&(Jt=function(n){if(!jt(n))throw new le;return Ce.apply(e,arguments)});var He=8==$e(d+"08")?$e:function(n,t){return $e(Ct(n)?n.replace(N,""):n,t||0)};return Z.after=function(n,t){if(!jt(t))throw new le;return function(){return 1>--n?t.apply(this,arguments):void 0}},Z.assign=H,Z.at=function(n){for(var t=arguments,e=-1,r=at(t,true,false,1),t=t[2]&&t[2][t[1]]===n?1:r.length,u=ne(t);++e<t;)u[e]=n[r[e]];return u},Z.bind=Gt,Z.bindAll=function(n){for(var t=1<arguments.length?at(arguments,true,false,1):dt(n),e=-1,r=t.length;++e<r;){var u=t[e];
n[u]=vt(n[u],1,null,null,n)}return n},Z.bindKey=function(n,t){return 2<arguments.length?vt(t,19,p(arguments,2),null,n):vt(t,3,null,null,n)},Z.chain=function(n){return n=new nt(n),n.__chain__=true,n},Z.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},Z.compose=function(){for(var n=arguments,t=n.length;t--;)if(!jt(n[t]))throw new le;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]}},Z.countBy=Ue,Z.create=function(n,t){var e=rt(n);
return t?H(e,t):e},Z.createCallback=function(n,t,e){var r=typeof n;if(null==n||"function"==r)return ut(n,t,e);if("object"!=r)return function(t){return t[n]};var u=ze(n),o=u[0],i=n[o];return 1!=u.length||i!==i||kt(i)?function(t){for(var e=u.length,r=false;e--&&(r=ft(t[u[e]],n[u[e]],null,true)););return r}:function(n){return n=n[o],i===n&&(0!==i||1/i==1/n)}},Z.curry=function(n,t){return t=typeof t=="number"?t:+t||n.length,vt(n,4,null,null,null,t)},Z.debounce=Ht,Z.defaults=V,Z.defer=Jt,Z.delay=function(n,t){if(!jt(n))throw new le;
var e=p(arguments,2);return ke(function(){n.apply(v,e)},t)},Z.difference=function(n){return it(n,at(arguments,true,true,1))},Z.filter=St,Z.flatten=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=typeof t!="function"&&r&&r[t]===n?null:t,t=false),null!=e&&(n=Dt(n,e,r)),at(n,t)},Z.forEach=Rt,Z.forEachRight=At,Z.forIn=b,Z.forInRight=function(n,t,e){var r=[];b(n,function(n,t){r.push(t,n)});var u=r.length;for(t=ut(t,e,3);u--&&false!==t(r[u--],r[u],n););return n},Z.forOwn=g,Z.forOwnRight=bt,Z.functions=dt,Z.groupBy=Ve,Z.indexBy=Ge,Z.initial=function(n,t,e){var r=0,u=n?n.length:0;
if(typeof t!="number"&&null!=t){var o=u;for(t=Z.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return p(n,0,De(Ae(0,u-r),u))},Z.intersection=function(e){for(var r=arguments,u=r.length,i=-1,f=a(),p=-1,s=gt(),v=e?e.length:0,h=[],g=a();++i<u;){var y=r[i];f[i]=s===n&&(y?y.length:0)>=_&&o(i?r[i]:g)}n:for(;++p<v;){var m=f[0],y=e[p];if(0>(m?t(m,y):s(g,y))){for(i=u,(m||g).push(y);--i;)if(m=f[i],0>(m?t(m,y):s(r[i],y)))continue n;h.push(y)}}for(;u--;)(m=f[u])&&c(m);return l(f),l(g),h},Z.invert=wt,Z.invoke=function(n,t){var e=p(arguments,2),r=-1,u=typeof t=="function",o=n?n.length:0,i=ne(typeof o=="number"?o:0);
return Rt(n,function(n){i[++r]=(u?t:n[t]).apply(n,e)}),i},Z.keys=ze,Z.map=Dt,Z.max=$t,Z.memoize=function(n,t){function e(){var r=e.cache,u=t?t.apply(this,arguments):m+arguments[0];return de.call(r,u)?r[u]:r[u]=n.apply(this,arguments)}if(!jt(n))throw new le;return e.cache={},e},Z.merge=function(n){var t=arguments,e=2;if(!kt(n))return n;if("number"!=typeof t[2]&&(e=t.length),3<e&&"function"==typeof t[e-2])var r=ut(t[--e-1],t[e--],2);else 2<e&&"function"==typeof t[e-1]&&(r=t[--e]);for(var t=p(arguments,1,e),u=-1,o=a(),i=a();++u<e;)lt(n,t[u],r,o,i);
return l(o),l(i),n},Z.min=function(n,t,e){var u=1/0,o=u;if(typeof t!="function"&&e&&e[t]===n&&(t=null),null==t&&qe(n)){e=-1;for(var i=n.length;++e<i;){var a=n[e];a<o&&(o=a)}}else t=null==t&&Ct(n)?r:Z.createCallback(t,e,3),Rt(n,function(n,e,r){e=t(n,e,r),e<u&&(u=e,o=n)});return o},Z.omit=function(n,t,e){var r={};if(typeof t!="function"){var u=[];b(n,function(n,t){u.push(t)});for(var u=it(u,at(arguments,true,false,1)),o=-1,i=u.length;++o<i;){var a=u[o];r[a]=n[a]}}else t=Z.createCallback(t,e,3),b(n,function(n,e,u){t(n,e,u)||(r[e]=n)
});return r},Z.once=function(n){var t,e;if(!jt(n))throw new le;return function(){return t?e:(t=true,e=n.apply(this,arguments),n=null,e)}},Z.pairs=function(n){for(var t=-1,e=ze(n),r=e.length,u=ne(r);++t<r;){var o=e[t];u[t]=[o,n[o]]}return u},Z.partial=function(n){return vt(n,16,p(arguments,1))},Z.partialRight=function(n){return vt(n,32,null,p(arguments,1))},Z.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=-1,o=at(arguments,true,false,1),i=kt(n)?o.length:0;++u<i;){var a=o[u];a in n&&(r[a]=n[a])
}else t=Z.createCallback(t,e,3),b(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},Z.pluck=Ft,Z.pull=function(n){for(var t=arguments,e=0,r=t.length,u=n?n.length:0;++e<r;)for(var o=-1,i=t[e];++o<u;)n[o]===i&&(xe.call(n,o--,1),u--);return n},Z.range=function(n,t,e){n=+n||0,e=typeof e=="number"?e:+e||1,null==t&&(t=n,n=0);var r=-1;t=Ae(0,ge((t-n)/(e||1)));for(var u=ne(t);++r<t;)u[r]=n,n+=e;return u},Z.reject=function(n,t,e){return t=Z.createCallback(t,e,3),St(n,function(n,e,r){return!t(n,e,r)})},Z.remove=function(n,t,e){var r=-1,u=n?n.length:0,o=[];
for(t=Z.createCallback(t,e,3);++r<u;)e=n[r],t(e,r,n)&&(o.push(e),xe.call(n,r--,1),u--);return o},Z.rest=Kt,Z.shuffle=Wt,Z.sortBy=function(n,t,e){var r=-1,o=n?n.length:0,i=ne(typeof o=="number"?o:0);for(t=Z.createCallback(t,e,3),Rt(n,function(n,e,u){var o=i[++r]=f();o.m=t(n,e,u),o.n=r,o.o=n}),o=i.length,i.sort(u);o--;)n=i[o],i[o]=n.o,c(n);return i},Z.tap=function(n,t){return t(n),n},Z.throttle=function(n,t,e){var r=true,u=true;if(!jt(n))throw new le;return false===e?r=false:kt(e)&&(r="leading"in e?e.leading:r,u="trailing"in e?e.trailing:u),L.leading=r,L.maxWait=t,L.trailing=u,Ht(n,t,L)
},Z.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=ne(n);for(t=ut(t,e,1);++r<n;)u[r]=t(r);return u},Z.toArray=function(n){return n&&typeof n.length=="number"?p(n):Ot(n)},Z.transform=function(n,t,e,r){var u=qe(n);if(null==e)if(u)e=[];else{var o=n&&n.constructor;e=rt(o&&o.prototype)}return t&&(t=Z.createCallback(t,r,4),(u?Rt:g)(n,function(n,r,u){return t(e,n,r,u)})),e},Z.union=function(){return pt(at(arguments,true,true))},Z.uniq=Mt,Z.values=Ot,Z.where=St,Z.without=function(n){return it(n,p(arguments,1))
},Z.wrap=function(n,t){return vt(t,16,[n])},Z.zip=Ut,Z.zipObject=Vt,Z.collect=Dt,Z.drop=Kt,Z.each=Rt,Z.eachRight=At,Z.extend=H,Z.methods=dt,Z.object=Vt,Z.select=St,Z.tail=Kt,Z.unique=Mt,Z.unzip=Ut,Xt(Z),Z.clone=function(n,t,e,r){return typeof t!="boolean"&&null!=t&&(r=e,e=t,t=false),et(n,t,typeof e=="function"&&ut(e,r,1))},Z.cloneDeep=function(n,t,e){return et(n,true,typeof t=="function"&&ut(t,e,1))},Z.contains=It,Z.escape=function(n){return null==n?"":fe(n).replace(Me,ht)},Z.every=Nt,Z.find=Et,Z.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;
for(t=Z.createCallback(t,e,3);++r<u;)if(t(n[r],r,n))return r;return-1},Z.findKey=function(n,t,e){var r;return t=Z.createCallback(t,e,3),g(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0}),r},Z.findLast=function(n,t,e){var r;return t=Z.createCallback(t,e,3),At(n,function(n,e,u){return t(n,e,u)?(r=n,false):void 0}),r},Z.findLastIndex=function(n,t,e){var r=n?n.length:0;for(t=Z.createCallback(t,e,3);r--;)if(t(n[r],r,n))return r;return-1},Z.findLastKey=function(n,t,e){var r;return t=Z.createCallback(t,e,3),bt(n,function(n,e,u){return t(n,e,u)?(r=e,false):void 0
}),r},Z.has=function(n,t){return n?de.call(n,t):false},Z.identity=Qt,Z.indexOf=Pt,Z.isArguments=_t,Z.isArray=qe,Z.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&ve.call(n)==F||false},Z.isDate=function(n){return n&&typeof n=="object"&&ve.call(n)==T||false},Z.isElement=function(n){return n&&1===n.nodeType||false},Z.isEmpty=function(n){var t=true;if(!n)return t;var e=ve.call(n),r=n.length;return e==$||e==P||e==D||e==q&&typeof r=="number"&&jt(n.splice)?!r:(g(n,function(){return t=false}),t)},Z.isEqual=function(n,t,e,r){return ft(n,t,typeof e=="function"&&ut(e,r,2))
},Z.isFinite=function(n){return Se(n)&&!Ee(parseFloat(n))},Z.isFunction=jt,Z.isNaN=function(n){return xt(n)&&n!=+n},Z.isNull=function(n){return null===n},Z.isNumber=xt,Z.isObject=kt,Z.isPlainObject=h,Z.isRegExp=function(n){return n&&typeof n=="object"&&ve.call(n)==z||false},Z.isString=Ct,Z.isUndefined=function(n){return typeof n=="undefined"},Z.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?Ae(0,r+e):De(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},Z.mixin=Xt,Z.noConflict=function(){return e._=se,this
},Z.noop=Yt,Z.parseInt=He,Z.random=function(n,t,e){var r=null==n,u=null==t;return null==e&&(typeof n=="boolean"&&u?(e=n,n=1):u||typeof t!="boolean"||(e=t,u=true)),r&&u&&(t=1),n=+n||0,u?(t=n,n=0):t=+t||0,e||n%1||t%1?(e=Fe(),De(n+e*(t-n+parseFloat("1e-"+((e+"").length-1))),t)):ct(n,t)},Z.reduce=Tt,Z.reduceRight=Bt,Z.result=function(n,t){if(n){var e=n[t];return jt(e)?n[t]():e}},Z.runInContext=s,Z.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:ze(n).length},Z.some=qt,Z.sortedIndex=Lt,Z.template=function(n,t,e){var r=Z.templateSettings;
n=fe(n||""),e=V({},e,r);var u,o=V({},e.imports,r.imports),r=ze(o),o=Ot(o),a=0,f=e.interpolate||S,l="__p+='",f=ae((e.escape||S).source+"|"+f.source+"|"+(f===I?x:S).source+"|"+(e.evaluate||S).source+"|$","g");n.replace(f,function(t,e,r,o,f,c){return r||(r=o),l+=n.slice(a,c).replace(R,i),e&&(l+="'+__e("+e+")+'"),f&&(u=true,l+="';"+f+";\n__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),a=c+t.length,t}),l+="';",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(w,""):l).replace(j,"$1").replace(k,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";
try{var c=re(r,"return "+l).apply(v,o)}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},Z.unescape=function(n){return null==n?"":fe(n).replace(Le,mt)},Z.uniqueId=function(n){var t=++y;return fe(null==n?"":n)+t},Z.all=Nt,Z.any=qt,Z.detect=Et,Z.findWhere=Et,Z.foldl=Tt,Z.foldr=Bt,Z.include=It,Z.inject=Tt,g(Z,function(n,t){Z.prototype[t]||(Z.prototype[t]=function(){var t=[this.__wrapped__],e=this.__chain__;return je.apply(t,arguments),t=n.apply(Z,t),e?new nt(t,e):t})}),Z.first=zt,Z.last=function(n,t,e){var r=0,u=n?n.length:0;
if(typeof t!="number"&&null!=t){var o=u;for(t=Z.createCallback(t,e,3);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n?n[u-1]:v;return p(n,Ae(0,u-r))},Z.sample=function(n,t,e){return n&&typeof n.length!="number"&&(n=Ot(n)),null==t||e?n?n[ct(0,n.length-1)]:v:(n=Wt(n),n.length=De(Ae(0,t),n.length),n)},Z.take=zt,Z.head=zt,g(Z,function(n,t){var e="sample"!==t;Z.prototype[t]||(Z.prototype[t]=function(t,r){var u=this.__chain__,o=n(this.__wrapped__,t,r);return u||null!=t&&(!r||e&&typeof t=="function")?new nt(o,u):o
})}),Z.VERSION="2.3.0",Z.prototype.chain=function(){return this.__chain__=true,this},Z.prototype.toString=function(){return fe(this.__wrapped__)},Z.prototype.value=Zt,Z.prototype.valueOf=Zt,Rt(["join","pop","shift"],function(n){var t=ce[n];Z.prototype[n]=function(){var n=this.__chain__,e=t.apply(this.__wrapped__,arguments);return n?new nt(e,n):e}}),Rt(["push","reverse","sort","unshift"],function(n){var t=ce[n];Z.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),Rt(["concat","slice","splice"],function(n){var t=ce[n];
Z.prototype[n]=function(){return new nt(t.apply(this.__wrapped__,arguments),this.__chain__)}}),Z}var v,h=[],g=[],y=0,m=+new Date+"",_=75,b=40,d=" \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",w=/\b__p\+='';/g,j=/\b(__p\+=)''\+/g,k=/(__e\(.*?\)|\b__t\))\+'';/g,x=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,C=/\w*$/,O=/^\s*function[ \n\r\t]+\w/,I=/<%=([\s\S]+?)%>/g,N=RegExp("^["+d+"]*0+(?=.$)"),S=/($^)/,E=/\bthis\b/,R=/['\n\r\t\u2028\u2029\\]/g,A="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),D="[object Arguments]",$="[object Array]",F="[object Boolean]",T="[object Date]",B="[object Function]",W="[object Number]",q="[object Object]",z="[object RegExp]",P="[object String]",K={};
K[B]=false,K[D]=K[$]=K[F]=K[T]=K[W]=K[q]=K[z]=K[P]=true;var L={leading:false,maxWait:0,trailing:false},M={configurable:false,enumerable:false,value:null,writable:false},U={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},V={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},G=U[typeof window]&&window||this,H=U[typeof exports]&&exports&&!exports.nodeType&&exports,J=U[typeof module]&&module&&!module.nodeType&&module,Q=J&&J.exports===H&&H,X=U[typeof global]&&global;!X||X.global!==X&&X.window!==X||(G=X);
var Y=s();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(G._=Y, define(function(){return Y})):H&&J?Q?(J.exports=Y)._=Y:H._=Y:G._=Y}).call(this);
;!function(n){function t(n,t,e){e=(e||0)-1;for(var r=n.length;++e<r;)if(n[e]===t)return e;return-1}function e(n,e){var r=typeof e;if(n=n.k,"boolean"==r||e==y)return n[e];"number"!=r&&"string"!=r&&(r="object");var u="number"==r?e:j+e;return n=n[r]||(n[r]={}),"object"==r?n[u]&&-1<t(n[u],e)?0:-1:n[u]?0:-1}function r(n){var t=this.k,e=typeof n;if("boolean"==e||n==y)t[n]=h;else{"number"!=e&&"string"!=e&&(e="object");var r="number"==e?n:j+n,u=t[e]||(t[e]={});"object"==e?(u[r]||(u[r]=[])).push(n)==this.b.length&&(t[e]=b):u[r]=h
}}function u(n){return n.charCodeAt(0)}function a(n,t){var e=n.m,r=t.m;if(n=n.l,t=t.l,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1}return e<r?-1:1}function o(n){var t=-1,e=n.length,u=l();u["false"]=u["null"]=u["true"]=u.undefined=b;var a=l();for(a.b=n,a.k=u,a.push=r;++t<e;)a.push(n[t]);return u.object===false?(p(a),y):a}function i(n){return"\\"+Q[n]}function f(){return m.pop()||[]}function l(){return d.pop()||{b:y,l:y,"false":b,m:0,leading:b,maxWait:0,"null":b,number:y,object:y,push:y,string:y,trailing:b,"true":b,undefined:b,n:y}
}function c(n){m.length==C&&(m.length=C-1),n.length=0,m.push(n)}function p(n){var t=n.k;t&&p(t),d.length==C&&(d.length=C-1),n.b=n.k=n.l=n.object=n.number=n.string=n.n=y,d.push(n)}function s(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Array(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function v(r){function m(n){if(!n||ve.call(n)!=V)return b;var t=n.valueOf,e=typeof t=="function"&&(e=fe(t))&&fe(e);return e?n==e||fe(n)==e:it(n)}function d(n,t,e){if(!n||!L[typeof n])return n;
t=t&&typeof e=="undefined"?t:tt.createCallback(t,e);for(var r=-1,u=L[typeof n]&&Se(n),a=u?u.length:0;++r<a&&(e=u[r],!(t(n[e],e,n)===false)););return n}function C(n,t,e){var r;if(!n||!L[typeof n])return n;t=t&&typeof e=="undefined"?t:tt.createCallback(t,e);for(r in n)if(t(n[r],r,n)===false)break;return n}function Q(n,t,e){var r,u=n,a=u;if(!u)return a;for(var o=arguments,i=0,f=typeof e=="number"?2:o.length;++i<f;)if((u=o[i])&&L[typeof u])for(var l=-1,c=L[typeof u]&&Se(u),p=c?c.length:0;++l<p;)r=c[l],"undefined"==typeof a[r]&&(a[r]=u[r]);
return a}function X(n,t,e){var r,u=n,a=u;if(!u)return a;var o=arguments,i=0,f=typeof e=="number"?2:o.length;if(3<f&&"function"==typeof o[f-2])var l=tt.createCallback(o[--f-1],o[f--],2);else 2<f&&"function"==typeof o[f-1]&&(l=o[--f]);for(;++i<f;)if((u=o[i])&&L[typeof u])for(var c=-1,p=L[typeof u]&&Se(u),s=p?p.length:0;++c<s;)r=p[c],a[r]=l?l(a[r],u[r]):u[r];return a}function Z(n){var t,e=[];if(!n||!L[typeof n])return e;for(t in n)le.call(n,t)&&e.push(t);return e}function tt(n){return n&&typeof n=="object"&&!Ee(n)&&le.call(n,"__wrapped__")?n:new et(n)
}function et(n){this.__wrapped__=n}function rt(n,t,e,r){function u(){var r=arguments,l=o?this:t;return a||(n=t[i]),e.length&&(r=r.length?(r=Ce.call(r),f?r.concat(e):e.concat(r)):e),this instanceof u?(l=gt(n.prototype)?he(n.prototype):{},r=n.apply(l,r),gt(r)?r:l):n.apply(l,r)}var a=vt(n),o=!e,i=t;if(o){var f=r;e=t}else if(!a){if(!r)throw new Yt;t=n}return u}function ut(n){return Ie[n]}function at(){var n=(n=tt.indexOf)===$t?t:n;return n}function ot(n){return function(t,e,r,u){return typeof e!="boolean"&&e!=y&&(u=r,r=u&&u[e]===t?g:e,e=b),r!=y&&(r=tt.createCallback(r,u)),n(t,e,r,u)
}}function it(n){var t,e;return n&&ve.call(n)==V&&(t=n.constructor,!vt(t)||t instanceof t)?(C(n,function(n,t){e=t}),e===g||le.call(n,e)):b}function ft(n){return Ae[n]}function lt(n,t,e,r,u,a){var o=n;if(typeof t!="boolean"&&t!=y&&(r=e,e=t,t=b),typeof e=="function"){if(e=typeof r=="undefined"?e:tt.createCallback(e,r,1),o=e(o),typeof o!="undefined")return o;o=n}if(r=gt(o)){var i=ve.call(o);if(!J[i])return o;var l=Ee(o)}if(!r||!t)return r?l?s(o):X({},o):o;switch(r=xe[i],i){case P:case K:return new r(+o);
case U:case H:return new r(o);case G:return r(o.source,A.exec(o))}i=!u,u||(u=f()),a||(a=f());for(var p=u.length;p--;)if(u[p]==n)return a[p];return o=l?r(o.length):{},l&&(le.call(n,"index")&&(o.index=n.index),le.call(n,"input")&&(o.input=n.input)),u.push(n),a.push(o),(l?wt:d)(n,function(n,r){o[r]=lt(n,t,e,g,u,a)}),i&&(c(u),c(a)),o}function ct(n){var t=[];return C(n,function(n,e){vt(n)&&t.push(e)}),t.sort()}function pt(n){for(var t=-1,e=Se(n),r=e.length,u={};++t<r;){var a=e[t];u[n[a]]=a}return u}function st(n,t,e,r,u,a){var o=e===k;
if(typeof e=="function"&&!o){e=tt.createCallback(e,r,2);var i=e(n,t);if(typeof i!="undefined")return!!i}if(n===t)return 0!==n||1/n==1/t;var l=typeof n,p=typeof t;if(n===n&&(!n||"function"!=l&&"object"!=l)&&(!t||"function"!=p&&"object"!=p))return b;if(n==y||t==y)return n===t;if(p=ve.call(n),l=ve.call(t),p==z&&(p=V),l==z&&(l=V),p!=l)return b;switch(p){case P:case K:return+n==+t;case U:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case G:case H:return n==Xt(t)}if(l=p==W,!l){if(le.call(n,"__wrapped__")||le.call(t,"__wrapped__"))return st(n.__wrapped__||n,t.__wrapped__||t,e,r,u,a);
if(p!=V)return b;var p=n.constructor,s=t.constructor;if(p!=s&&(!vt(p)||!(p instanceof p&&vt(s)&&s instanceof s)))return b}for(s=!u,u||(u=f()),a||(a=f()),p=u.length;p--;)if(u[p]==n)return a[p]==t;var v=0,i=h;if(u.push(n),a.push(t),l){if(p=n.length,v=t.length,i=v==n.length,!i&&!o)return i;for(;v--;)if(l=p,s=t[v],o)for(;l--&&!(i=st(n[l],s,e,r,u,a)););else if(!(i=st(n[v],s,e,r,u,a)))break;return i}return C(t,function(t,o,f){return le.call(f,o)?(v++,i=le.call(n,o)&&st(n[o],t,e,r,u,a)):void 0}),i&&!o&&C(n,function(n,t,e){return le.call(e,t)?i=-1<--v:void 0
}),s&&(c(u),c(a)),i}function vt(n){return typeof n=="function"}function gt(n){return!(!n||!L[typeof n])}function ht(n){return typeof n=="number"||ve.call(n)==U}function yt(n){return typeof n=="string"||ve.call(n)==H}function bt(n,t,e){var r=arguments,u=0,a=2;if(!gt(n))return n;if(e===k)var o=r[3],i=r[4],l=r[5];else{var p=h,i=f(),l=f();typeof e!="number"&&(a=r.length),3<a&&"function"==typeof r[a-2]?o=tt.createCallback(r[--a-1],r[a--],2):2<a&&"function"==typeof r[a-1]&&(o=r[--a])}for(;++u<a;)(Ee(r[u])?wt:d)(r[u],function(t,e){var r,u,a=t,f=n[e];
if(t&&((u=Ee(t))||m(t))){for(a=i.length;a--;)if(r=i[a]==t){f=l[a];break}if(!r){var c;o&&(a=o(f,t),c=typeof a!="undefined")&&(f=a),c||(f=u?Ee(f)?f:[]:m(f)?f:{}),i.push(t),l.push(f),c||(f=bt(f,t,k,o,i,l))}}else o&&(a=o(f,t),typeof a=="undefined"&&(a=t)),typeof a!="undefined"&&(f=a);n[e]=f});return p&&(c(i),c(l)),n}function mt(n){for(var t=-1,e=Se(n),r=e.length,u=Mt(r);++t<r;)u[t]=n[e[t]];return u}function dt(n,t,e){var r=-1,u=at(),a=n?n.length:0,o=b;return e=(0>e?_e(0,a+e):e)||0,a&&typeof a=="number"?o=-1<(yt(n)?n.indexOf(t,e):u(n,t,e)):d(n,function(n){return++r<e?void 0:!(o=n===t)
}),o}function _t(n,t,e){var r=h;t=tt.createCallback(t,e),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&(r=!!t(n[e],e,n)););else d(n,function(n,e,u){return r=!!t(n,e,u)});return r}function kt(n,t,e){var r=[];t=tt.createCallback(t,e),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u;){var a=n[e];t(a,e,n)&&r.push(a)}else d(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function jt(n,t,e){t=tt.createCallback(t,e),e=-1;var r=n?n.length:0;if(typeof r!="number"){var u;return d(n,function(n,e,r){return t(n,e,r)?(u=n,b):void 0
}),u}for(;++e<r;){var a=n[e];if(t(a,e,n))return a}}function wt(n,t,e){var r=-1,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:tt.createCallback(t,e),typeof u=="number")for(;++r<u&&t(n[r],r,n)!==false;);else d(n,t);return n}function Ct(n,t,e){var r=-1,u=n?n.length:0;if(t=tt.createCallback(t,e),typeof u=="number")for(var a=Mt(u);++r<u;)a[r]=t(n[r],r,n);else a=[],d(n,function(n,e,u){a[++r]=t(n,e,u)});return a}function xt(n,t,e){var r=-1/0,a=r;if(!t&&Ee(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];i>a&&(a=i)
}}else t=!t&&yt(n)?u:tt.createCallback(t,e),wt(n,function(n,e,u){e=t(n,e,u),e>r&&(r=e,a=n)});return a}function Ot(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number")for(var u=Mt(r);++e<r;)u[e]=n[e][t];return u||Ct(n,t)}function Et(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=tt.createCallback(t,r,4);var a=-1,o=n.length;if(typeof o=="number")for(u&&(e=n[++a]);++a<o;)e=t(e,n[a],a,n);else d(n,function(n,r,a){e=u?(u=b,n):t(e,n,r,a)});return e}function St(n,t,e,r){var u=n?n.length:0,a=3>arguments.length;
if(typeof u!="number")var o=Se(n),u=o.length;return t=tt.createCallback(t,r,4),wt(n,function(r,i,f){i=o?o[--u]:--u,e=a?(a=b,n[i]):t(e,n[i],i,f)}),e}function It(n,t,e){var r;t=tt.createCallback(t,e),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&!(r=t(n[e],e,n)););else d(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function At(n){var r=-1,u=at(),a=n?n.length:0,i=ae.apply(Zt,Ce.call(arguments,1)),f=[],l=a>=w&&u===t;if(l){var c=o(i);c?(u=e,i=c):l=b}for(;++r<a;)c=n[r],0>u(i,c)&&f.push(c);
return l&&p(i),f}function Nt(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&t!=y){var a=-1;for(t=tt.createCallback(t,e);++a<u&&t(n[a],a,n);)r++}else if(r=t,r==y||e)return n[0];return s(n,0,ke(_e(0,r),u))}}function $t(n,e,r){if(typeof r=="number"){var u=n?n.length:0;r=0>r?_e(0,u+r):r||0}else if(r)return r=Ft(n,e),n[r]===e?r:-1;return n?t(n,e,r):-1}function Bt(n,t,e){if(typeof t!="number"&&t!=y){var r=0,u=-1,a=n?n.length:0;for(t=tt.createCallback(t,e);++u<a&&t(n[u],u,n);)r++}else r=t==y||e?1:_e(0,t);
return s(n,r)}function Ft(n,t,e,r){var u=0,a=n?n.length:u;for(e=e?tt.createCallback(e,r,1):Wt,t=e(t);u<a;)r=u+a>>>1,e(n[r])<t?u=r+1:a=r;return u}function Rt(n){for(var t=-1,e=n?xt(Ot(n,"length")):0,r=Mt(0>e?0:e);++t<e;)r[t]=Ot(n,t);return r}function Tt(n,t){for(var e=-1,r=n?n.length:0,u={};++e<r;){var a=n[e];t?u[a]=t[e]:u[a[0]]=a[1]}return u}function qt(n,t){return Oe.fastBind||ge&&2<arguments.length?ge.call.apply(ge,arguments):rt(n,t,Ce.call(arguments,2))}function Dt(n,t,e){function r(){ue(s),ue(v),l=0,s=v=y
}function u(){var t=g&&(!m||1<l);r(),t&&(p!==false&&(c=new Vt),i=n.apply(f,o))}function a(){r(),(g||p!==t)&&(c=new Vt,i=n.apply(f,o))}var o,i,f,l=0,c=0,p=b,s=y,v=y,g=h;if(t=_e(0,t||0),e===h)var m=h,g=b;else gt(e)&&(m=e.leading,p="maxWait"in e&&_e(t,e.maxWait||0),g="trailing"in e?e.trailing:g);return function(){if(o=arguments,f=this,l++,ue(v),p===false)m&&2>l&&(i=n.apply(f,o));else{var e=new Vt;!s&&!m&&(c=e);var r=p-(e-c);0<r?s||(s=se(a,r)):(ue(s),s=y,c=e,i=n.apply(f,o))}return t!==p&&(v=se(u,t)),i}}function zt(n){var t=Ce.call(arguments,1);
return se(function(){n.apply(g,t)},1)}function Wt(n){return n}function Pt(n){wt(ct(n),function(t){var e=tt[t]=n[t];tt.prototype[t]=function(){var n=this.__wrapped__,t=[n];return ce.apply(t,arguments),t=e.apply(tt,t),n&&typeof n=="object"&&n===t?this:new et(t)}})}function Kt(){return this.__wrapped__}r=r?nt.defaults(n.Object(),r,nt.pick(n,D)):n;var Mt=r.Array,Ut=r.Boolean,Vt=r.Date,Gt=r.Function,Ht=r.Math,Jt=r.Number,Lt=r.Object,Qt=r.RegExp,Xt=r.String,Yt=r.TypeError,Zt=[],ne=Lt.prototype,te=r._,ee=Qt("^"+Xt(ne.valueOf).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),re=Ht.ceil,ue=r.clearTimeout,ae=Zt.concat,oe=Ht.floor,ie=Gt.prototype.toString,fe=ee.test(fe=Lt.getPrototypeOf)&&fe,le=ne.hasOwnProperty,ce=Zt.push,pe=r.setImmediate,se=r.setTimeout,ve=ne.toString,ge=ee.test(ge=ve.bind)&&ge,he=ee.test(he=Lt.create)&&he,ye=ee.test(ye=Mt.isArray)&&ye,be=r.isFinite,me=r.isNaN,de=ee.test(de=Lt.keys)&&de,_e=Ht.max,ke=Ht.min,je=r.parseInt,we=Ht.random,Ce=Zt.slice,Ht=ee.test(r.attachEvent),Ht=ge&&!/\n|true/.test(ge+Ht),xe={};
xe[W]=Mt,xe[P]=Ut,xe[K]=Vt,xe[M]=Gt,xe[V]=Lt,xe[U]=Jt,xe[G]=Qt,xe[H]=Xt,et.prototype=tt.prototype;var Oe=tt.support={};Oe.fastBind=ge&&!Ht,tt.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:N,variable:"",imports:{_:tt}};var Ee=ye,Se=de?function(n){return gt(n)?de(n):[]}:Z,Ie={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Ae=pt(Ie),Ut=ot(function $e(n,t,e){for(var r=-1,u=n?n.length:0,a=[];++r<u;){var o=n[r];e&&(o=e(o,r,n)),Ee(o)?ce.apply(a,t?o:$e(o)):a.push(o)
}return a}),Ne=ot(function(n,r,u){var a=-1,i=at(),l=n?n.length:0,s=[],v=!r&&l>=w&&i===t,g=u||v?f():s;if(v){var h=o(g);h?(i=e,g=h):(v=b,g=u?g:(c(g),s))}for(;++a<l;){var h=n[a],y=u?u(h,a,n):h;(r?!a||g[g.length-1]!==y:0>i(g,y))&&((u||v)&&g.push(y),s.push(h))}return v?(c(g.b),p(g)):u&&c(g),s});return Ht&&Y&&typeof pe=="function"&&(zt=qt(pe,r)),pe=8==je(B+"08")?je:function(n,t){return je(yt(n)?n.replace(F,""):n,t||0)},tt.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0
}},tt.assign=X,tt.at=function(n){for(var t=-1,e=ae.apply(Zt,Ce.call(arguments,1)),r=e.length,u=Mt(r);++t<r;)u[t]=n[e[t]];return u},tt.bind=qt,tt.bindAll=function(n){for(var t=1<arguments.length?ae.apply(Zt,Ce.call(arguments,1)):ct(n),e=-1,r=t.length;++e<r;){var u=t[e];n[u]=qt(n[u],n)}return n},tt.bindKey=function(n,t){return rt(n,t,Ce.call(arguments,2),k)},tt.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},tt.compose=function(){var n=arguments;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];
return t[0]}},tt.countBy=function(n,t,e){var r={};return t=tt.createCallback(t,e),wt(n,function(n,e,u){e=Xt(t(n,e,u)),le.call(r,e)?r[e]++:r[e]=1}),r},tt.createCallback=function(n,t,e){if(n==y)return Wt;var r=typeof n;if("function"!=r){if("object"!=r)return function(t){return t[n]};var u=Se(n);return function(t){for(var e=u.length,r=b;e--&&(r=st(t[u[e]],n[u[e]],k)););return r}}return typeof t=="undefined"||$&&!$.test(ie.call(n))?n:1===e?function(e){return n.call(t,e)}:2===e?function(e,r){return n.call(t,e,r)
}:4===e?function(e,r,u,a){return n.call(t,e,r,u,a)}:function(e,r,u){return n.call(t,e,r,u)}},tt.debounce=Dt,tt.defaults=Q,tt.defer=zt,tt.delay=function(n,t){var e=Ce.call(arguments,2);return se(function(){n.apply(g,e)},t)},tt.difference=At,tt.filter=kt,tt.flatten=Ut,tt.forEach=wt,tt.forIn=C,tt.forOwn=d,tt.functions=ct,tt.groupBy=function(n,t,e){var r={};return t=tt.createCallback(t,e),wt(n,function(n,e,u){e=Xt(t(n,e,u)),(le.call(r,e)?r[e]:r[e]=[]).push(n)}),r},tt.initial=function(n,t,e){if(!n)return[];
var r=0,u=n.length;if(typeof t!="number"&&t!=y){var a=u;for(t=tt.createCallback(t,e);a--&&t(n[a],a,n);)r++}else r=t==y||e?1:t||r;return s(n,0,ke(_e(0,u-r),u))},tt.intersection=function(n){for(var r=arguments,u=r.length,a=-1,i=f(),l=-1,s=at(),v=n?n.length:0,g=[],h=f();++a<u;){var y=r[a];i[a]=s===t&&(y?y.length:0)>=w&&o(a?r[a]:h)}n:for(;++l<v;){var b=i[0],y=n[l];if(0>(b?e(b,y):s(h,y))){for(a=u,(b||h).push(y);--a;)if(b=i[a],0>(b?e(b,y):s(r[a],y)))continue n;g.push(y)}}for(;u--;)(b=i[u])&&p(b);return c(i),c(h),g
},tt.invert=pt,tt.invoke=function(n,t){var e=Ce.call(arguments,2),r=-1,u=typeof t=="function",a=n?n.length:0,o=Mt(typeof a=="number"?a:0);return wt(n,function(n){o[++r]=(u?t:n[t]).apply(n,e)}),o},tt.keys=Se,tt.map=Ct,tt.max=xt,tt.memoize=function(n,t){function e(){var r=e.cache,u=j+(t?t.apply(this,arguments):arguments[0]);return le.call(r,u)?r[u]:r[u]=n.apply(this,arguments)}return e.cache={},e},tt.merge=bt,tt.min=function(n,t,e){var r=1/0,a=r;if(!t&&Ee(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];
i<a&&(a=i)}}else t=!t&&yt(n)?u:tt.createCallback(t,e),wt(n,function(n,e,u){e=t(n,e,u),e<r&&(r=e,a=n)});return a},tt.omit=function(n,t,e){var r=at(),u=typeof t=="function",a={};if(u)t=tt.createCallback(t,e);else var o=ae.apply(Zt,Ce.call(arguments,1));return C(n,function(n,e,i){(u?!t(n,e,i):0>r(o,e))&&(a[e]=n)}),a},tt.once=function(n){var t,e;return function(){return t?e:(t=h,e=n.apply(this,arguments),n=y,e)}},tt.pairs=function(n){for(var t=-1,e=Se(n),r=e.length,u=Mt(r);++t<r;){var a=e[t];u[t]=[a,n[a]]
}return u},tt.partial=function(n){return rt(n,Ce.call(arguments,1))},tt.partialRight=function(n){return rt(n,Ce.call(arguments,1),y,k)},tt.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=-1,a=ae.apply(Zt,Ce.call(arguments,1)),o=gt(n)?a.length:0;++u<o;){var i=a[u];i in n&&(r[i]=n[i])}else t=tt.createCallback(t,e),C(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},tt.pluck=Ot,tt.range=function(n,t,e){n=+n||0,e=+e||1,t==y&&(t=n,n=0);var r=-1;t=_e(0,re((t-n)/e));for(var u=Mt(t);++r<t;)u[r]=n,n+=e;
return u},tt.reject=function(n,t,e){return t=tt.createCallback(t,e),kt(n,function(n,e,r){return!t(n,e,r)})},tt.rest=Bt,tt.shuffle=function(n){var t=-1,e=n?n.length:0,r=Mt(typeof e=="number"?e:0);return wt(n,function(n){var e=oe(we()*(++t+1));r[t]=r[e],r[e]=n}),r},tt.sortBy=function(n,t,e){var r=-1,u=n?n.length:0,o=Mt(typeof u=="number"?u:0);for(t=tt.createCallback(t,e),wt(n,function(n,e,u){var a=o[++r]=l();a.l=t(n,e,u),a.m=r,a.n=n}),u=o.length,o.sort(a);u--;)n=o[u],o[u]=n.n,p(n);return o},tt.tap=function(n,t){return t(n),n
},tt.throttle=function(n,t,e){var r=h,u=h;return e===false?r=b:gt(e)&&(r="leading"in e?e.leading:r,u="trailing"in e?e.trailing:u),e=l(),e.leading=r,e.maxWait=t,e.trailing=u,n=Dt(n,t,e),p(e),n},tt.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=Mt(n);for(t=tt.createCallback(t,e,1);++r<n;)u[r]=t(r);return u},tt.toArray=function(n){return n&&typeof n.length=="number"?s(n):mt(n)},tt.transform=function(n,t,e,r){var u=Ee(n);return t=tt.createCallback(t,r,4),e==y&&(u?e=[]:(r=n&&n.constructor,e=gt(r&&r.prototype)?he(r&&r.prototype):{})),(u?wt:d)(n,function(n,r,u){return t(e,n,r,u)
}),e},tt.union=function(n){return Ee(n)||(arguments[0]=n?Ce.call(n):Zt),Ne(ae.apply(Zt,arguments))},tt.uniq=Ne,tt.unzip=Rt,tt.values=mt,tt.where=kt,tt.without=function(n){return At(n,Ce.call(arguments,1))},tt.wrap=function(n,t){return function(){var e=[n];return ce.apply(e,arguments),t.apply(this,e)}},tt.zip=function(n){return n?Rt(arguments):[]},tt.zipObject=Tt,tt.collect=Ct,tt.drop=Bt,tt.each=wt,tt.extend=X,tt.methods=ct,tt.object=Tt,tt.select=kt,tt.tail=Bt,tt.unique=Ne,Pt(tt),tt.chain=tt,tt.prototype.chain=function(){return this
},tt.clone=lt,tt.cloneDeep=function(n,t,e){return lt(n,h,t,e)},tt.contains=dt,tt.escape=function(n){return n==y?"":Xt(n).replace(T,ut)},tt.every=_t,tt.find=jt,tt.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=tt.createCallback(t,e);++r<u;)if(t(n[r],r,n))return r;return-1},tt.findKey=function(n,t,e){var r;return t=tt.createCallback(t,e),d(n,function(n,e,u){return t(n,e,u)?(r=e,b):void 0}),r},tt.has=function(n,t){return n?le.call(n,t):b},tt.identity=Wt,tt.indexOf=$t,tt.isArguments=function(n){return ve.call(n)==z
},tt.isArray=Ee,tt.isBoolean=function(n){return n===h||n===false||ve.call(n)==P},tt.isDate=function(n){return n?typeof n=="object"&&ve.call(n)==K:b},tt.isElement=function(n){return n?1===n.nodeType:b},tt.isEmpty=function(n){var t=h;if(!n)return t;var e=ve.call(n),r=n.length;return e==W||e==H||e==z||e==V&&typeof r=="number"&&vt(n.splice)?!r:(d(n,function(){return t=b}),t)},tt.isEqual=st,tt.isFinite=function(n){return be(n)&&!me(parseFloat(n))},tt.isFunction=vt,tt.isNaN=function(n){return ht(n)&&n!=+n
},tt.isNull=function(n){return n===y},tt.isNumber=ht,tt.isObject=gt,tt.isPlainObject=m,tt.isRegExp=function(n){return n?typeof n=="object"&&ve.call(n)==G:b},tt.isString=yt,tt.isUndefined=function(n){return typeof n=="undefined"},tt.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?_e(0,r+e):ke(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},tt.mixin=Pt,tt.noConflict=function(){return r._=te,this},tt.parseInt=pe,tt.random=function(n,t){n==y&&t==y&&(t=1),n=+n||0,t==y?(t=n,n=0):t=+t||0;
var e=we();return n%1||t%1?n+ke(e*(t-n+parseFloat("1e-"+((e+"").length-1))),t):n+oe(e*(t-n+1))},tt.reduce=Et,tt.reduceRight=St,tt.result=function(n,t){var e=n?n[t]:g;return vt(e)?n[t]():e},tt.runInContext=v,tt.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Se(n).length},tt.some=It,tt.sortedIndex=Ft,tt.template=function(n,t,e){var r=tt.templateSettings;n||(n=""),e=Q({},e,r);var u,a=Q({},e.imports,r.imports),r=Se(a),a=mt(a),o=0,f=e.interpolate||R,l="__p+='",f=Qt((e.escape||R).source+"|"+f.source+"|"+(f===N?I:R).source+"|"+(e.evaluate||R).source+"|$","g");
n.replace(f,function(t,e,r,a,f,c){return r||(r=a),l+=n.slice(o,c).replace(q,i),e&&(l+="'+__e("+e+")+'"),f&&(u=h,l+="';"+f+";__p+='"),r&&(l+="'+((__t=("+r+"))==null?'':__t)+'"),o=c+t.length,t}),l+="';\n",f=e=e.variable,f||(e="obj",l="with("+e+"){"+l+"}"),l=(u?l.replace(x,""):l).replace(O,"$1").replace(E,"$1;"),l="function("+e+"){"+(f?"":e+"||("+e+"={});")+"var __t,__p='',__e=_.escape"+(u?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}";try{var c=Gt(r,"return "+l).apply(g,a)
}catch(p){throw p.source=l,p}return t?c(t):(c.source=l,c)},tt.unescape=function(n){return n==y?"":Xt(n).replace(S,ft)},tt.uniqueId=function(n){var t=++_;return Xt(n==y?"":n)+t},tt.all=_t,tt.any=It,tt.detect=jt,tt.findWhere=jt,tt.foldl=Et,tt.foldr=St,tt.include=dt,tt.inject=Et,d(tt,function(n,t){tt.prototype[t]||(tt.prototype[t]=function(){var t=[this.__wrapped__];return ce.apply(t,arguments),n.apply(tt,t)})}),tt.first=Nt,tt.last=function(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&t!=y){var a=u;
for(t=tt.createCallback(t,e);a--&&t(n[a],a,n);)r++}else if(r=t,r==y||e)return n[u-1];return s(n,_e(0,u-r))}},tt.take=Nt,tt.head=Nt,d(tt,function(n,t){tt.prototype[t]||(tt.prototype[t]=function(t,e){var r=n(this.__wrapped__,t,e);return t==y||e&&typeof t!="function"?r:new et(r)})}),tt.VERSION="1.3.0",tt.prototype.toString=function(){return Xt(this.__wrapped__)},tt.prototype.value=Kt,tt.prototype.valueOf=Kt,wt(["join","pop","shift"],function(n){var t=Zt[n];tt.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)
}}),wt(["push","reverse","sort","unshift"],function(n){var t=Zt[n];tt.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),wt(["concat","slice","splice"],function(n){var t=Zt[n];tt.prototype[n]=function(){return new et(t.apply(this.__wrapped__,arguments))}}),tt}var g,h=!0,y=null,b=!1,m=[],d=[],_=0,k={},j=+new Date+"",w=75,C=10,x=/\b__p\+='';/g,O=/\b(__p\+=)''\+/g,E=/(__e\(.*?\)|\b__t\))\+'';/g,S=/&(?:amp|lt|gt|quot|#39);/g,I=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,A=/\w*$/,N=/<%=([\s\S]+?)%>/g,$=($=/\bthis\b/)&&$.test(v)&&$,B=" \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",F=RegExp("^["+B+"]*0+(?=.$)"),R=/($^)/,T=/[&<>"']/g,q=/['\n\r\t\u2028\u2029\\]/g,D="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),z="[object Arguments]",W="[object Array]",P="[object Boolean]",K="[object Date]",M="[object Function]",U="[object Number]",V="[object Object]",G="[object RegExp]",H="[object String]",J={};
J[M]=b,J[z]=J[W]=J[P]=J[K]=J[U]=J[V]=J[G]=J[H]=h;var L={"boolean":b,"function":h,object:h,number:b,string:b,undefined:b},Q={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},X=L[typeof exports]&&exports,Y=L[typeof module]&&module&&module.exports==X&&module,Z=L[typeof global]&&global;!Z||Z.global!==Z&&Z.window!==Z||(n=Z);var nt=v();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=nt, define(function(){return nt})):X&&!X.nodeType?Y?(Y.exports=nt)._=nt:X._=nt:n._=nt
}(this);

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,35 @@
/**
* @license
* Lo-Dash 2.3.0 (Custom Build) lodash.com/license | Underscore.js 1.5.2 underscorejs.org/LICENSE
* Lo-Dash 1.3.0 (Custom Build) lodash.com/license
* Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(){function n(n,r,t){t=(t||0)-1;for(var e=n?n.length:0;++t<e;)if(n[t]===r)return t;return-1}function r(n,r){var t=n.m,e=r.m;if(t!==e){if(t>e||typeof t=="undefined")return 1;if(t<e||typeof e=="undefined")return-1}return n.n-r.n}function t(n){return"\\"+vr[n]}function e(n,r,t){r||(r=0),typeof t=="undefined"&&(t=n?n.length:0);var e=-1;t=t-r||0;for(var u=Array(0>t?0:t);++e<t;)u[e]=n[r+e];return u}function u(n){return n instanceof u?n:new o(n)}function o(n,r){this.__chain__=!!r,this.__wrapped__=n
}function i(n){function r(){if(e){var n=e.slice();Rr.apply(n,arguments)}if(this instanceof r){var o=f(t.prototype),n=t.apply(o,n||arguments);return T(n)?n:o}return t.apply(u,n||arguments)}var t=n[0],e=n[2],u=n[4];return r}function f(n){return T(n)?Br(n):{}}function a(n,r,t){if(typeof n!="function")return Y;if(typeof r=="undefined"||!("prototype"in n))return n;switch(t){case 1:return function(t){return n.call(r,t)};case 2:return function(t,e){return n.call(r,t,e)};case 3:return function(t,e,u){return n.call(r,t,e,u)
};case 4:return function(t,e,u,o){return n.call(r,t,e,u,o)}}return L(n,r)}function l(n){function r(){var n=p?a:this;if(o){var y=o.slice();Rr.apply(y,arguments)}return(i||g)&&(y||(y=e(arguments)),i&&Rr.apply(y,i),g&&y.length<c)?(u|=16,l([t,h?u:-4&u,y,null,a,c])):(y||(y=arguments),s&&(t=n[v]),this instanceof r?(n=f(t.prototype),y=t.apply(n,y),T(y)?y:n):t.apply(n,y))}var t=n[0],u=n[1],o=n[2],i=n[3],a=n[4],c=n[5],p=1&u,s=2&u,g=4&u,h=8&u,v=t;return r}function c(n,r){for(var t=-1,e=m(),u=n?n.length:0,o=[];++t<u;){var i=n[t];
0>e(r,i)&&o.push(i)}return o}function p(n,r,t,e){e=(e||0)-1;for(var u=n?n.length:0,o=[];++e<u;){var i=n[e];if(i&&typeof i=="object"&&typeof i.length=="number"&&(Cr(i)||d(i))){r||(i=p(i,r,t));var f=-1,a=i.length,l=o.length;for(o.length+=a;++f<a;)o[l++]=i[f]}else t||o.push(i)}return o}function s(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(n===n&&!(n&&hr[typeof n]||r&&hr[typeof r]))return false;if(null==n||null==r)return n===r;var o=Ar.call(n),i=Ar.call(r);if(o!=i)return false;switch(o){case ar:case lr:return+n==+r;
case cr:return n!=+n?r!=+r:0==n?1/n==1/r:n==+r;case sr:case gr:return n==r+""}if(i=o==fr,!i){var f=n instanceof u,a=r instanceof u;if(f||a)return s(f?n.__wrapped__:n,a?r.__wrapped__:r,t,e);if(o!=pr)return false;if(o=n.constructor,f=r.constructor,o!=f&&!(E(o)&&o instanceof o&&E(f)&&f instanceof f)&&"constructor"in n&&"constructor"in r)return false}for(t||(t=[]),e||(e=[]),o=t.length;o--;)if(t[o]==n)return e[o]==r;var l=true,c=0;if(t.push(n),e.push(r),i){if(c=r.length,l=c==n.length)for(;c--&&(l=s(n[c],r[c],t,e)););return l
}return Kr(r,function(r,u,o){return Sr.call(o,u)?(c++,!(l=Sr.call(n,u)&&s(n[u],r,t,e))&&tr):void 0}),l&&Kr(n,function(n,r,t){return Sr.call(t,r)?!(l=-1<--c)&&tr:void 0}),l}function g(n,r,t){for(var e=-1,u=m(),o=n?n.length:0,i=[],f=t?[]:i;++e<o;){var a=n[e],l=t?t(a,e,n):a;(r?!e||f[f.length-1]!==l:0>u(f,l))&&(t&&f.push(l),i.push(a))}return i}function h(n){return function(r,t,e){var u={};t=Q(t,e,3),e=-1;var o=r?r.length:0;if(typeof o=="number")for(;++e<o;){var i=r[e];n(u,i,t(i,e,r),r)}else Lr(r,function(r,e,o){n(u,r,t(r,e,o),o)
});return u}}function v(n,r,t,e,u,o){var f=16&r,a=32&r;if(!(2&r||E(n)))throw new TypeError;return f&&!t.length&&(r&=-17,t=false),a&&!e.length&&(r&=-33,e=false),(1==r||17===r?i:l)([n,r,t,e,u,o])}function y(n){return Vr[n]}function m(){var r=(r=u.indexOf)===G?n:r;return r}function _(n){return Gr[n]}function d(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ar.call(n)==ir||false}function b(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)n[u]=e[u]}return n
}function w(n){if(!n)return n;for(var r=1,t=arguments.length;r<t;r++){var e=arguments[r];if(e)for(var u in e)"undefined"==typeof n[u]&&(n[u]=e[u])}return n}function j(n){var r=[];return Kr(n,function(n,t){E(n)&&r.push(t)}),r.sort()}function x(n){for(var r=-1,t=Ur(n),e=t.length,u={};++r<e;){var o=t[r];u[n[o]]=o}return u}function A(n){if(!n)return true;if(Cr(n)||S(n))return!n.length;for(var r in n)if(Sr.call(n,r))return false;return true}function E(n){return typeof n=="function"}function T(n){return!(!n||!hr[typeof n])
}function O(n){return typeof n=="number"||n&&typeof n=="object"&&Ar.call(n)==cr||false}function S(n){return typeof n=="string"||n&&typeof n=="object"&&Ar.call(n)==gr||false}function N(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];return u}function R(n,r){var t=m(),e=n?n.length:0,u=false;return e&&typeof e=="number"?u=-1<t(n,r):Lr(n,function(n){return(u=n===r)&&tr}),u}function k(n,r,t){var e=true;r=Q(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&(e=!!r(n[t],t,n)););else Lr(n,function(n,t,u){return!(e=!!r(n,t,u))&&tr
});return e}function B(n,r,t){var e=[];r=Q(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u;){var o=n[t];r(o,t,n)&&e.push(o)}else Lr(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function F(n,r,t){r=Q(r,t,3),t=-1;var e=n?n.length:0;if(typeof e!="number"){var u;return Lr(n,function(n,t,e){return r(n,t,e)?(u=n,tr):void 0}),u}for(;++t<e;){var o=n[t];if(r(o,t,n))return o}}function q(n,r,t){var e=-1,u=n?n.length:0;if(r=r&&typeof t=="undefined"?r:a(r,t,3),typeof u=="number")for(;++e<u&&r(n[e],e,n)!==tr;);else Lr(n,r)
}function D(n,r){var t=n?n.length:0;if(typeof t=="number")for(;t--&&false!==r(n[t],t,n););else{var e=Ur(n),t=e.length;Lr(n,function(n,u,o){return u=e?e[--t]:--t,false===r(o[u],u,o)&&tr})}}function I(n,r,t){var e=-1,u=n?n.length:0;if(r=Q(r,t,3),typeof u=="number")for(var o=Array(u);++e<u;)o[e]=r(n[e],e,n);else o=[],Lr(n,function(n,t,u){o[++e]=r(n,t,u)});return o}function M(n,r,t){var e=-1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t>u&&(u=t);
else r=Q(r,t,3),q(n,function(n,t,o){t=r(n,t,o),t>e&&(e=t,u=n)});return u}function $(n,r){var t=-1,e=n?n.length:0;if(typeof e=="number")for(var u=Array(e);++t<e;)u[t]=n[t][r];return u||I(n,r)}function W(n,r,t,e){if(!n)return t;var u=3>arguments.length;r=Q(r,e,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(t=n[++o]);++o<i;)t=r(t,n[o],o,n);else Lr(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)});return t}function z(n,r,t,e){var u=3>arguments.length;return r=Q(r,e,4),D(n,function(n,e,o){t=u?(u=false,n):r(t,n,e,o)
}),t}function C(n){var r=-1,t=n?n.length:0,e=Array(typeof t=="number"?t:0);return q(n,function(n){var t;t=++r,t=0+Or(Wr()*(t-0+1)),e[r]=e[t],e[t]=n}),e}function P(n,r,t){var e;r=Q(r,t,3),t=-1;var u=n?n.length:0;if(typeof u=="number")for(;++t<u&&!(e=r(n[t],t,n)););else Lr(n,function(n,t,u){return(e=r(n,t,u))&&tr});return!!e}function U(n,r,t){return t&&A(r)?nr:(t?F:B)(n,r)}function V(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=-1;for(r=Q(r,t,3);++i<o&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[0]:nr;
return e(n,0,$r(Mr(0,u),o))}function G(r,t,e){if(typeof e=="number"){var u=r?r.length:0;e=0>e?Mr(0,u+e):e||0}else if(e)return e=J(r,t),r[e]===t?e:-1;return n(r,t,e)}function H(n,r,t){if(typeof r!="number"&&null!=r){var u=0,o=-1,i=n?n.length:0;for(r=Q(r,t,3);++o<i&&r(n[o],o,n);)u++}else u=null==r||t?1:Mr(0,r);return e(n,u)}function J(n,r,t,e){var u=0,o=n?n.length:u;for(t=t?Q(t,e,1):Y,r=t(r);u<o;)e=u+o>>>1,t(n[e])<r?u=e+1:o=e;return u}function K(n,r,t,e){return typeof r!="boolean"&&null!=r&&(e=t,t=typeof r!="function"&&e&&e[r]===n?null:r,r=false),null!=t&&(t=Q(t,e,3)),g(n,r,t)
}function L(n,r){return 2<arguments.length?v(n,17,e(arguments,2),null,r):v(n,1,null,null,r)}function Q(n,r,t){var e=typeof n;if(null==n||"function"==e)return a(n,r,t);if("object"!=e)return function(r){return r[n]};var u=Ur(n);return function(r){for(var t=u.length,e=false;t--&&(e=r[u[t]]===n[u[t]]););return e}}function X(n,r,t){var e,u,o,i,f,a,l,c=0,p=false,s=true;if(!E(n))throw new TypeError;if(r=Mr(0,r)||0,true===t)var g=true,s=false;else T(t)&&(g=t.leading,p="maxWait"in t&&(Mr(r,t.maxWait)||0),s="trailing"in t?t.trailing:s);
var h=function(){var t=r-(Nr()-i);0<t?a=setTimeout(h,t):(u&&clearTimeout(u),t=l,u=a=l=nr,t&&(c=Nr(),o=n.apply(f,e),a||u||(e=f=null)))},v=function(){a&&clearTimeout(a),u=a=l=nr,(s||p!==r)&&(c=Nr(),o=n.apply(f,e),a||u||(e=f=null))};return function(){if(e=arguments,i=Nr(),f=this,l=s&&(a||!g),false===p)var t=g&&!a;else{u||g||(c=i);var y=p-(i-c),m=0>=y;m?(u&&(u=clearTimeout(u)),c=i,o=n.apply(f,e)):u||(u=setTimeout(v,y))}return m&&a?a=clearTimeout(a):a||r===p||(a=setTimeout(h,r)),t&&(m=true,o=n.apply(f,e)),!m||a||u||(e=f=null),o
}}function Y(n){return n}function Z(n){q(j(n),function(r){var t=u[r]=n[r];u.prototype[r]=function(){var n=[this.__wrapped__];return Rr.apply(n,arguments),n=t.apply(u,n),this.__chain__?new o(n,true):n}})}var nr,rr=0,tr={},er=+new Date+"",ur=/($^)/,or=/['\n\r\t\u2028\u2029\\]/g,ir="[object Arguments]",fr="[object Array]",ar="[object Boolean]",lr="[object Date]",cr="[object Number]",pr="[object Object]",sr="[object RegExp]",gr="[object String]",hr={"boolean":false,"function":true,object:true,number:false,string:false,undefined:false},vr={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},yr=hr[typeof window]&&window||this,mr=hr[typeof exports]&&exports&&!exports.nodeType&&exports,_r=hr[typeof module]&&module&&!module.nodeType&&module,dr=_r&&_r.exports===mr&&mr,br=hr[typeof global]&&global;
!br||br.global!==br&&br.window!==br||(yr=br);var wr=[],jr=Object.prototype,xr=yr._,Ar=jr.toString,Er=RegExp("^"+(Ar+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),Tr=Math.ceil,Or=Math.floor,Sr=jr.hasOwnProperty,Nr=Er.test(Nr=Date.now)&&Nr||function(){return+new Date},Rr=wr.push,kr=jr.propertyIsEnumerable,Br=Er.test(Br=Object.create)&&Br,Fr=Er.test(Fr=Array.isArray)&&Fr,qr=yr.isFinite,Dr=yr.isNaN,Ir=Er.test(Ir=Object.keys)&&Ir,Mr=Math.max,$r=Math.min,Wr=Math.random;
o.prototype=u.prototype;var zr={};!function(){var n={0:1,length:1};zr.spliceObjects=(wr.splice.call(n,0,1),!n[0])}(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Br||(f=function(){function n(){}return function(r){if(T(r)){n.prototype=r;var t=new n;n.prototype=null}return t||yr.Object()}}()),d(arguments)||(d=function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Sr.call(n,"callee")&&!kr.call(n,"callee")||false});var Cr=Fr||function(n){return n&&typeof n=="object"&&typeof n.length=="number"&&Ar.call(n)==fr||false
},Pr=function(n){var r,t=[];if(!n||!hr[typeof n])return t;for(r in n)Sr.call(n,r)&&t.push(r);return t},Ur=Ir?function(n){return T(n)?Ir(n):[]}:Pr,Vr={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},Gr=x(Vr),Hr=RegExp("("+Ur(Gr).join("|")+")","g"),Jr=RegExp("["+Ur(Vr).join("")+"]","g"),Kr=function(n,r){var t;if(!n||!hr[typeof n])return n;for(t in n)if(r(n[t],t,n)===tr)break;return n},Lr=function(n,r){var t;if(!n||!hr[typeof n])return n;for(t in n)if(Sr.call(n,t)&&r(n[t],t,n)===tr)break;
return n};E(/x/)&&(E=function(n){return typeof n=="function"&&"[object Function]"==Ar.call(n)});var Qr=h(function(n,r,t){Sr.call(n,t)?n[t]++:n[t]=1}),Xr=h(function(n,r,t){(Sr.call(n,t)?n[t]:n[t]=[]).push(r)}),Yr=h(function(n,r,t){n[t]=r});u.after=function(n,r){if(!E(r))throw new TypeError;return function(){return 1>--n?r.apply(this,arguments):void 0}},u.bind=L,u.bindAll=function(n){for(var r=1<arguments.length?p(arguments,true,false,1):j(n),t=-1,e=r.length;++t<e;){var u=r[t];n[u]=v(n[u],1,null,null,n)}return n
},u.chain=function(n){return n=new o(n),n.__chain__=true,n},u.compact=function(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e},u.compose=function(){for(var n=arguments,r=n.length;r--;)if(!E(n[r]))throw new TypeError;return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}},u.countBy=Qr,u.debounce=X,u.defaults=w,u.defer=function(n){if(!E(n))throw new TypeError;var r=e(arguments,1);return setTimeout(function(){n.apply(nr,r)},1)},u.delay=function(n,r){if(!E(n))throw new TypeError;
var t=e(arguments,2);return setTimeout(function(){n.apply(nr,t)},r)},u.difference=function(n){return c(n,p(arguments,true,true,1))},u.filter=B,u.flatten=function(n,r){return p(n,r)},u.forEach=q,u.functions=j,u.groupBy=Xr,u.indexBy=Yr,u.initial=function(n,r,t){var u=0,o=n?n.length:0;if(typeof r!="number"&&null!=r){var i=o;for(r=Q(r,t,3);i--&&r(n[i],i,n);)u++}else u=null==r||t?1:r||u;return e(n,0,$r(Mr(0,o-u),o))},u.intersection=function(n){var r=arguments,t=r.length,e=-1,u=m(),o=n?n.length:0,i=[];n:for(;++e<o;){var f=n[e];
if(0>u(i,f)){for(var a=t;--a;)if(0>u(r[a],f))continue n;i.push(f)}}return i},u.invert=x,u.invoke=function(n,r){var t=e(arguments,2),u=-1,o=typeof r=="function",i=n?n.length:0,f=Array(typeof i=="number"?i:0);return q(n,function(n){f[++u]=(o?r:n[r]).apply(n,t)}),f},u.keys=Ur,u.map=I,u.max=M,u.memoize=function(n,r){var t={};return function(){var e=r?r.apply(this,arguments):er+arguments[0];return Sr.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}},u.min=function(n,r,t){var e=1/0,u=e;typeof r!="function"&&t&&t[r]===n&&(r=null);
var o=-1,i=n?n.length:0;if(null==r&&typeof i=="number")for(;++o<i;)t=n[o],t<u&&(u=t);else r=Q(r,t,3),q(n,function(n,t,o){t=r(n,t,o),t<e&&(e=t,u=n)});return u},u.omit=function(n){var r=[];Kr(n,function(n,t){r.push(t)});for(var r=c(r,p(arguments,true,false,1)),t=-1,e=r.length,u={};++t<e;){var o=r[t];u[o]=n[o]}return u},u.once=function(n){var r,t;if(!E(n))throw new TypeError;return function(){return r?t:(r=true,t=n.apply(this,arguments),n=null,t)}},u.pairs=function(n){for(var r=-1,t=Ur(n),e=t.length,u=Array(e);++r<e;){var o=t[r];
u[r]=[o,n[o]]}return u},u.partial=function(n){return v(n,16,e(arguments,1))},u.pick=function(n){for(var r=-1,t=p(arguments,true,false,1),e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u},u.pluck=$,u.range=function(n,r,t){n=+n||0,t=+t||1,null==r&&(r=n,n=0);var e=-1;r=Mr(0,Tr((r-n)/t));for(var u=Array(r);++e<r;)u[e]=n,n+=t;return u},u.reject=function(n,r,t){return r=Q(r,t,3),B(n,function(n,t,e){return!r(n,t,e)})},u.rest=H,u.shuffle=C,u.sortBy=function(n,t,e){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);
for(t=Q(t,e,3),q(n,function(n,r,e){i[++u]={m:t(n,r,e),n:u,o:n}}),o=i.length,i.sort(r);o--;)i[o]=i[o].o;return i},u.tap=function(n,r){return r(n),n},u.throttle=function(n,r,t){var e=true,u=true;if(!E(n))throw new TypeError;return false===t?e=false:T(t)&&(e="leading"in t?t.leading:e,u="trailing"in t?t.trailing:u),t={},t.leading=e,t.maxWait=r,t.trailing=u,X(n,r,t)},u.times=function(n,r,t){n=-1<(n=+n)?n:0;var e=-1,u=Array(n);for(r=a(r,t,1);++e<n;)u[e]=r(e);return u},u.toArray=function(n){return Cr(n)?e(n):n&&typeof n.length=="number"?I(n):N(n)
},u.union=function(){return g(p(arguments,true,true))},u.uniq=K,u.values=N,u.where=U,u.without=function(n){return c(n,e(arguments,1))},u.wrap=function(n,r){return v(r,16,[n])},u.zip=function(){for(var n=-1,r=M($(arguments,"length")),t=Array(0>r?0:r);++n<r;)t[n]=$(arguments,n);return t},u.collect=I,u.drop=H,u.each=q,u.extend=b,u.methods=j,u.object=function(n,r){for(var t=-1,e=n?n.length:0,u={};++t<e;){var o=n[t];r?u[o]=r[t]:o&&(u[o[0]]=o[1])}return u},u.select=B,u.tail=H,u.unique=K,u.clone=function(n){return T(n)?Cr(n)?e(n):b({},n):n
},u.contains=R,u.escape=function(n){return null==n?"":(n+"").replace(Jr,y)},u.every=k,u.find=F,u.has=function(n,r){return n?Sr.call(n,r):false},u.identity=Y,u.indexOf=G,u.isArguments=d,u.isArray=Cr,u.isBoolean=function(n){return true===n||false===n||n&&typeof n=="object"&&Ar.call(n)==ar||false},u.isDate=function(n){return n&&typeof n=="object"&&Ar.call(n)==lr||false},u.isElement=function(n){return n&&1===n.nodeType||false},u.isEmpty=A,u.isEqual=function(n,r){return s(n,r)},u.isFinite=function(n){return qr(n)&&!Dr(parseFloat(n))
},u.isFunction=E,u.isNaN=function(n){return O(n)&&n!=+n},u.isNull=function(n){return null===n},u.isNumber=O,u.isObject=T,u.isRegExp=function(n){return n&&hr[typeof n]&&Ar.call(n)==sr||false},u.isString=S,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,r,t){var e=n?n.length:0;for(typeof t=="number"&&(e=(0>t?Mr(0,e+t):$r(t,e-1))+1);e--;)if(n[e]===r)return e;return-1},u.mixin=Z,u.noConflict=function(){return yr._=xr,this},u.random=function(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r?(r=n,n=0):r=+r||0,n+Or(Wr()*(r-n+1))
},u.reduce=W,u.reduceRight=z,u.result=function(n,r){if(n){var t=n[r];return E(t)?n[r]():t}},u.size=function(n){var r=n?n.length:0;return typeof r=="number"?r:Ur(n).length},u.some=P,u.sortedIndex=J,u.template=function(n,r,e){var o=u,i=o.templateSettings;n=(n||"")+"",e=w({},e,i);var f=0,a="__p+='",i=e.variable;n.replace(RegExp((e.escape||ur).source+"|"+(e.interpolate||ur).source+"|"+(e.evaluate||ur).source+"|$","g"),function(r,e,u,o,i){return a+=n.slice(f,i).replace(or,t),e&&(a+="'+_.escape("+e+")+'"),o&&(a+="';"+o+";\n__p+='"),u&&(a+="'+((__t=("+u+"))==null?'':__t)+'"),f=i+r.length,r
}),a+="';",i||(i="obj",a="with("+i+"||{}){"+a+"}"),a="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+a+"return __p}";try{var l=Function("_","return "+a)(o)}catch(c){throw c.source=a,c}return r?l(r):(l.source=a,l)},u.unescape=function(n){return null==n?"":(n+"").replace(Hr,_)},u.uniqueId=function(n){var r=++rr+"";return n?n+r:r},u.all=k,u.any=P,u.detect=F,u.findWhere=function(n,r){return U(n,r,true)},u.foldl=W,u.foldr=z,u.include=R,u.inject=W,u.first=V,u.last=function(n,r,t){var u=0,o=n?n.length:0;
if(typeof r!="number"&&null!=r){var i=o;for(r=Q(r,t,3);i--&&r(n[i],i,n);)u++}else if(u=r,null==u||t)return n?n[o-1]:nr;return e(n,Mr(0,o-u))},u.sample=function(n,r,t){return n&&typeof n.length!="number"&&(n=N(n)),null==r||t?n?n[0+Or(Wr()*(n.length-1-0+1))]:nr:(n=C(n),n.length=$r(Mr(0,r),n.length),n)},u.take=V,u.head=V,Z(u),u.VERSION="2.3.0",u.prototype.chain=function(){return this.__chain__=true,this},u.prototype.value=function(){return this.__wrapped__},q("pop push reverse shift sort splice unshift".split(" "),function(n){var r=wr[n];
u.prototype[n]=function(){var n=this.__wrapped__;return r.apply(n,arguments),zr.spliceObjects||0!==n.length||delete n[0],this}}),q(["concat","join","slice"],function(n){var r=wr[n];u.prototype[n]=function(){var n=r.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new o(n),n.__chain__=true),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(yr._=u, define(function(){return u})):mr&&_r?dr?(_r.exports=u)._=u:mr._=u:yr._=u}).call(this);
;!function(n){function t(n,t){var r;if(n&&gt[typeof n])for(r in n)if(Et.call(n,r)&&t(n[r],r,n)===nt)break}function r(n,t){var r;if(n&&gt[typeof n])for(r in n)if(t(n[r],r,n)===nt)break}function e(n){var t,r=[];if(!n||!gt[typeof n])return r;for(t in n)Et.call(n,t)&&r.push(t);return r}function u(n,t,r){r=(r||0)-1;for(var e=n.length;++r<e;)if(n[r]===t)return r;return-1}function o(n,t){var r=n.m,e=t.m;if(n=n.l,t=t.l,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1}return r<e?-1:1
}function i(n){return"\\"+ht[n]}function a(){}function f(n){return n instanceof f?n:new c(n)}function c(n){this.__wrapped__=n}function l(n,t,r){function e(){var f=arguments,c=o?this:t;return u||(n=t[i]),r.length&&(f=f.length?(f=zt.call(f),a?f.concat(r):r.concat(f)):r),this instanceof e?(c=p(n.prototype),f=n.apply(c,f),A(f)?f:c):n.apply(c,f)}var u=w(n),o=!r,i=t;if(o){var a=void 0;r=t}else if(!u)throw new TypeError;return e}function p(n){return A(n)?Ft(n):{}}function s(n){return Wt[n]}function v(){var n=(n=f.indexOf)===U?u:n;
return n}function g(n){return Gt[n]}function h(n){return kt.call(n)==it}function y(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]=e[u]}return n}function m(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]==X&&(n[u]=e[u])}return n}function _(n){var t=[];return r(n,function(n,r){w(n)&&t.push(r)}),t.sort()}function d(n){for(var t=-1,r=Vt(n),e=r.length,u={};++t<e;){var o=r[t];u[n[o]]=o}return u}function b(n){if(!n)return Q;
if(Ut(n)||O(n))return!n.length;for(var t in n)if(Et.call(n,t))return Y;return Q}function j(n,t,e,u){if(n===t)return 0!==n||1/n==1/t;var o=typeof n,i=typeof t;if(n===n&&(!n||"function"!=o&&"object"!=o)&&(!t||"function"!=i&&"object"!=i))return Y;if(n==X||t==X)return n===t;if(i=kt.call(n),o=kt.call(t),i!=o)return Y;switch(i){case ft:case ct:return+n==+t;case lt:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case st:case vt:return n==t+""}if(o=i==at,!o){if(n instanceof f||t instanceof f)return j(n.__wrapped__||n,t.__wrapped__||t,e,u);
if(i!=pt)return Y;var i=n.constructor,a=t.constructor;if(i!=a&&(!w(i)||!(i instanceof i&&w(a)&&a instanceof a)))return Y}for(e||(e=[]),u||(u=[]),i=e.length;i--;)if(e[i]==n)return u[i]==t;var c=Q,l=0;if(e.push(n),u.push(t),o){if(l=t.length,c=l==n.length)for(;l--&&(c=j(n[l],t[l],e,u)););return c}return r(t,function(t,r,o){return Et.call(o,r)?(l++,!(c=Et.call(n,r)&&j(n[r],t,e,u))&&nt):void 0}),c&&r(n,function(n,t,r){return Et.call(r,t)?!(c=-1<--l)&&nt:void 0}),c}function w(n){return typeof n=="function"
}function A(n){return!(!n||!gt[typeof n])}function x(n){return typeof n=="number"||kt.call(n)==lt}function O(n){return typeof n=="string"||kt.call(n)==vt}function E(n){for(var t=-1,r=Vt(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function S(n,r){var e=v(),u=n?n.length:0,o=Y;return u&&typeof u=="number"?o=-1<e(n,r):t(n,function(n){return(o=n===r)&&nt}),o}function N(n,r,e){var u=Q;r=J(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o&&(u=!!r(n[e],e,n)););else t(n,function(n,t,e){return!(u=!!r(n,t,e))&&nt
});return u}function k(n,r,e){var u=[];r=J(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o;){var i=n[e];r(i,e,n)&&u.push(i)}else t(n,function(n,t,e){r(n,t,e)&&u.push(n)});return u}function B(n,r,e){r=J(r,e),e=-1;var u=n?n.length:0;if(typeof u!="number"){var o;return t(n,function(n,t,e){return r(n,t,e)?(o=n,nt):void 0}),o}for(;++e<u;){var i=n[e];if(r(i,e,n))return i}}function F(n,r,e){var u=-1,o=n?n.length:0;if(r=r&&typeof e=="undefined"?r:J(r,e),typeof o=="number")for(;++u<o&&r(n[u],u,n)!==nt;);else t(n,r)
}function q(n,r,e){var u=-1,o=n?n.length:0;if(r=J(r,e),typeof o=="number")for(var i=Array(o);++u<o;)i[u]=r(n[u],u,n);else i=[],t(n,function(n,t,e){i[++u]=r(n,t,e)});return i}function R(n,t,r){var e=-1/0,u=e,o=-1,i=n?n.length:0;if(t||typeof i!="number")t=J(t,r),F(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});else for(;++o<i;)r=n[o],r>u&&(u=r);return u}function D(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number")for(var u=Array(e);++r<e;)u[r]=n[r][t];return u||q(n,t)}function M(n,r,e,u){if(!n)return e;
var o=3>arguments.length;r=J(r,u,4);var i=-1,a=n.length;if(typeof a=="number")for(o&&(e=n[++i]);++i<a;)e=r(e,n[i],i,n);else t(n,function(n,t,u){e=o?(o=Y,n):r(e,n,t,u)});return e}function T(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=Vt(n),u=i.length;return t=J(t,e,4),F(n,function(e,a,f){a=i?i[--u]:--u,r=o?(o=Y,n[a]):t(r,n[a],a,f)}),r}function $(n,r,e){var u;r=J(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o&&!(u=r(n[e],e,n)););else t(n,function(n,t,e){return(u=r(n,t,e))&&nt
});return!!u}function I(n,t,r){return r&&b(t)?X:(r?B:k)(n,t)}function z(n){for(var t=-1,r=v(),e=n.length,u=xt.apply(dt,zt.call(arguments,1)),o=[];++t<e;){var i=n[t];0>r(u,i)&&o.push(i)}return o}function C(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=X){var o=-1;for(t=J(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==X||r)return n[0];return zt.call(n,0,$t(Tt(0,e),u))}}function P(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];Ut(o)?St.apply(u,t?o:P(o)):u.push(o)}return u}function U(n,t,r){if(typeof r=="number"){var e=n?n.length:0;
r=0>r?Tt(0,e+r):r||0}else if(r)return r=W(n,t),n[r]===t?r:-1;return n?u(n,t,r):-1}function V(n,t,r){if(typeof t!="number"&&t!=X){var e=0,u=-1,o=n?n.length:0;for(t=J(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==X||r?1:Tt(0,t);return zt.call(n,e)}function W(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?J(r,e,1):K,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function G(n,t,r,e){var u=-1,o=v(),i=n?n.length:0,a=[],f=a;for(typeof t!="boolean"&&t!=X&&(e=r,r=t,t=Y),r!=X&&(f=[],r=J(r,e));++u<i;){e=n[u];var c=r?r(e,u,n):e;
(t?!u||f[f.length-1]!==c:0>o(f,c))&&(r&&f.push(c),a.push(e))}return a}function H(n,t){return Pt.fastBind||Bt&&2<arguments.length?Bt.call.apply(Bt,arguments):l(n,t,zt.call(arguments,2))}function J(n,t,r){if(n==X)return K;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=Vt(n);return function(t){for(var r=u.length,e=Y;r--&&(e=t[u[r]]===n[u[r]]););return e}}return typeof t=="undefined"?n:1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)
}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}}function K(n){return n}function L(n){F(_(n),function(t){var r=f[t]=n[t];f.prototype[t]=function(){var n=[this.__wrapped__];return St.apply(n,arguments),n=r.apply(f,n),this.__chain__&&(n=new c(n),n.__chain__=Q),n}})}var Q=!0,X=null,Y=!1,Z=0,nt={},tt=+new Date+"",rt=/&(?:amp|lt|gt|quot|#39);/g,et=/($^)/,ut=/[&<>"']/g,ot=/['\n\r\t\u2028\u2029\\]/g,it="[object Arguments]",at="[object Array]",ft="[object Boolean]",ct="[object Date]",lt="[object Number]",pt="[object Object]",st="[object RegExp]",vt="[object String]",gt={"boolean":Y,"function":Q,object:Q,number:Y,string:Y,undefined:Y},ht={"\\":"\\","'":"'","\n":"n","\r":"r","\t":"t","\u2028":"u2028","\u2029":"u2029"},yt=gt[typeof exports]&&exports,mt=gt[typeof module]&&module&&module.exports==yt&&module,_t=gt[typeof global]&&global;
!_t||_t.global!==_t&&_t.window!==_t||(n=_t);var dt=[],_t=Object.prototype,bt=n._,jt=RegExp("^"+(_t.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),wt=Math.ceil,At=n.clearTimeout,xt=dt.concat,Ot=Math.floor,Et=_t.hasOwnProperty,St=dt.push,Nt=n.setTimeout,kt=_t.toString,Bt=jt.test(Bt=kt.bind)&&Bt,Ft=jt.test(Ft=Object.create)&&Ft,qt=jt.test(qt=Array.isArray)&&qt,Rt=n.isFinite,Dt=n.isNaN,Mt=jt.test(Mt=Object.keys)&&Mt,Tt=Math.max,$t=Math.min,It=Math.random,zt=dt.slice,_t=jt.test(n.attachEvent),Ct=Bt&&!/\n|true/.test(Bt+_t);
c.prototype=f.prototype;var Pt={};!function(){var n={0:1,length:1};Pt.fastBind=Bt&&!Ct,Pt.spliceObjects=(dt.splice.call(n,0,1),!n[0])}(1),f.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},Ft||(p=function(n){if(A(n)){a.prototype=n;var t=new a;a.prototype=X}return t||{}}),h(arguments)||(h=function(n){return n?Et.call(n,"callee"):Y});var Ut=qt||function(n){return n?typeof n=="object"&&kt.call(n)==at:Y},Vt=Mt?function(n){return A(n)?Mt(n):[]
}:e,Wt={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},Gt=d(Wt);w(/x/)&&(w=function(n){return typeof n=="function"&&"[object Function]"==kt.call(n)}),f.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},f.bind=H,f.bindAll=function(n){for(var t=1<arguments.length?xt.apply(dt,zt.call(arguments,1)):_(n),r=-1,e=t.length;++r<e;){var u=t[r];n[u]=H(n[u],n)}return n},f.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)
}return e},f.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},f.countBy=function(n,t,r){var e={};return t=J(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",Et.call(e,r)?e[r]++:e[r]=1}),e},f.debounce=function(n,t,r){function e(){a=X,r||(o=n.apply(i,u))}var u,o,i,a=X;return function(){var f=r&&!a;return u=arguments,i=this,At(a),a=Nt(e,t),f&&(o=n.apply(i,u)),o}},f.defaults=m,f.defer=function(n){var t=zt.call(arguments,1);return Nt(function(){n.apply(void 0,t)
},1)},f.delay=function(n,t){var r=zt.call(arguments,2);return Nt(function(){n.apply(void 0,r)},t)},f.difference=z,f.filter=k,f.flatten=P,f.forEach=F,f.functions=_,f.groupBy=function(n,t,r){var e={};return t=J(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",(Et.call(e,r)?e[r]:e[r]=[]).push(n)}),e},f.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=X){var o=u;for(t=J(t,r);o--&&t(n[o],o,n);)e++}else e=t==X||r?1:t||e;return zt.call(n,0,$t(Tt(0,u-e),u))},f.intersection=function(n){var t=arguments,r=t.length,e=-1,u=v(),o=n?n.length:0,i=[];
n:for(;++e<o;){var a=n[e];if(0>u(i,a)){for(var f=r;--f;)if(0>u(t[f],a))continue n;i.push(a)}}return i},f.invert=d,f.invoke=function(n,t){var r=zt.call(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return F(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},f.keys=Vt,f.map=q,f.max=R,f.memoize=function(n,t){var r={};return function(){var e=tt+(t?t.apply(this,arguments):arguments[0]);return Et.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},f.min=function(n,t,r){var e=1/0,u=e,o=-1,i=n?n.length:0;
if(t||typeof i!="number")t=J(t,r),F(n,function(n,r,o){r=t(n,r,o),r<e&&(e=r,u=n)});else for(;++o<i;)r=n[o],r<u&&(u=r);return u},f.omit=function(n){var t=v(),e=xt.apply(dt,zt.call(arguments,1)),u={};return r(n,function(n,r){0>t(e,r)&&(u[r]=n)}),u},f.once=function(n){var t,r;return function(){return t?r:(t=Q,r=n.apply(this,arguments),n=X,r)}},f.pairs=function(n){for(var t=-1,r=Vt(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},f.partial=function(n){return l(n,zt.call(arguments,1))
},f.pick=function(n){for(var t=-1,r=xt.apply(dt,zt.call(arguments,1)),e=r.length,u={};++t<e;){var o=r[t];o in n&&(u[o]=n[o])}return u},f.pluck=D,f.range=function(n,t,r){n=+n||0,r=+r||1,t==X&&(t=n,n=0);var e=-1;t=Tt(0,wt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},f.reject=function(n,t,r){return t=J(t,r),k(n,function(n,r,e){return!t(n,r,e)})},f.rest=V,f.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return F(n,function(n){var r=Ot(It()*(++t+1));e[t]=e[r],e[r]=n
}),e},f.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=J(t,r),F(n,function(n,r,u){i[++e]={l:t(n,r,u),m:e,n:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].n;return i},f.tap=function(n,t){return t(n),n},f.throttle=function(n,t){function r(){i=new Date,a=X,u=n.apply(o,e)}var e,u,o,i=0,a=X;return function(){var f=new Date,c=t-(f-i);return e=arguments,o=this,0<c?a||(a=Nt(r,c)):(At(a),a=X,i=f,u=n.apply(o,e)),u}},f.times=function(n,t,r){for(var e=-1,u=Array(-1<n?n:0);++e<n;)u[e]=t.call(r,e);
return u},f.toArray=function(n){return Ut(n)?zt.call(n):n&&typeof n.length=="number"?q(n):E(n)},f.union=function(n){return Ut(n)||(arguments[0]=n?zt.call(n):dt),G(xt.apply(dt,arguments))},f.uniq=G,f.values=E,f.where=I,f.without=function(n){return z(n,zt.call(arguments,1))},f.wrap=function(n,t){return function(){var r=[n];return St.apply(r,arguments),t.apply(this,r)}},f.zip=function(n){for(var t=-1,r=n?R(D(arguments,"length")):0,e=Array(0>r?0:r);++t<r;)e[t]=D(arguments,t);return e},f.collect=q,f.drop=V,f.each=F,f.extend=y,f.methods=_,f.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];
t?u[o]=t[r]:u[o[0]]=o[1]}return u},f.select=k,f.tail=V,f.unique=G,f.chain=function(n){return n=new c(n),n.__chain__=Q,n},f.clone=function(n){return A(n)?Ut(n)?zt.call(n):y({},n):n},f.contains=S,f.escape=function(n){return n==X?"":(n+"").replace(ut,s)},f.every=N,f.find=B,f.has=function(n,t){return n?Et.call(n,t):Y},f.identity=K,f.indexOf=U,f.isArguments=h,f.isArray=Ut,f.isBoolean=function(n){return n===Q||n===Y||kt.call(n)==ft},f.isDate=function(n){return n?typeof n=="object"&&kt.call(n)==ct:Y},f.isElement=function(n){return n?1===n.nodeType:Y
},f.isEmpty=b,f.isEqual=j,f.isFinite=function(n){return Rt(n)&&!Dt(parseFloat(n))},f.isFunction=w,f.isNaN=function(n){return x(n)&&n!=+n},f.isNull=function(n){return n===X},f.isNumber=x,f.isObject=A,f.isRegExp=function(n){return!(!n||!gt[typeof n])&&kt.call(n)==st},f.isString=O,f.isUndefined=function(n){return typeof n=="undefined"},f.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?Tt(0,e+r):$t(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},f.mixin=L,f.noConflict=function(){return n._=bt,this
},f.random=function(n,t){n==X&&t==X&&(t=1),n=+n||0,t==X?(t=n,n=0):t=+t||0;var r=It();return n%1||t%1?n+$t(r*(t-n+parseFloat("1e-"+((r+"").length-1))),t):n+Ot(r*(t-n+1))},f.reduce=M,f.reduceRight=T,f.result=function(n,t){var r=n?n[t]:X;return w(r)?n[t]():r},f.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Vt(n).length},f.some=$,f.sortedIndex=W,f.template=function(n,t,r){var e=f.templateSettings;n||(n=""),r=m({},r,e);var u=0,o="__p+='",e=r.variable;n.replace(RegExp((r.escape||et).source+"|"+(r.interpolate||et).source+"|"+(r.evaluate||et).source+"|$","g"),function(t,r,e,a,f){return o+=n.slice(u,f).replace(ot,i),r&&(o+="'+_['escape']("+r+")+'"),a&&(o+="';"+a+";__p+='"),e&&(o+="'+((__t=("+e+"))==null?'':__t)+'"),u=f+t.length,t
}),o+="';\n",e||(e="obj",o="with("+e+"||{}){"+o+"}"),o="function("+e+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+o+"return __p}";try{var a=Function("_","return "+o)(f)}catch(c){throw c.source=o,c}return t?a(t):(a.source=o,a)},f.unescape=function(n){return n==X?"":(n+"").replace(rt,g)},f.uniqueId=function(n){var t=++Z+"";return n?n+t:t},f.all=N,f.any=$,f.detect=B,f.findWhere=function(n,t){return I(n,t,Q)},f.foldl=M,f.foldr=T,f.include=S,f.inject=M,f.first=C,f.last=function(n,t,r){if(n){var e=0,u=n.length;
if(typeof t!="number"&&t!=X){var o=u;for(t=J(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==X||r)return n[u-1];return zt.call(n,Tt(0,u-e))}},f.take=C,f.head=C,f.VERSION="1.3.0",L(f),f.prototype.chain=function(){return this.__chain__=Q,this},f.prototype.value=function(){return this.__wrapped__},F("pop push reverse shift sort splice unshift".split(" "),function(n){var t=dt[n];f.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),!Pt.spliceObjects&&0===n.length&&delete n[0],this}}),F(["concat","join","slice"],function(n){var t=dt[n];
f.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new c(n),n.__chain__=Q),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=f, define(function(){return f})):yt&&!yt.nodeType?mt?(mt.exports=f)._=f:yt._=f:n._=f}(this);

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,36 @@
<?php
// cleanup requested file path
$filePath = isset($_GET['f']) ? $_GET['f'] : 'lodash';
$filePath = preg_replace('#(\.*[\/])+#', '', $filePath);
$filePath .= preg_match('/\.[a-z]+$/', $filePath) ? '' : '.js';
// cleanup requested filepath
$file = isset($_GET['f']) ? $_GET['f'] : 'lodash';
$file = preg_replace('#(\.*[\/])+#', '', $file);
$file .= preg_match('/\.[a-z]+$/', $file) ? '' : '.js';
// output filename
if (isset($_GET['o'])) {
$outputName = $_GET['o'];
$output = $_GET['o'];
} else if (isset($_SERVER['argv'][1])) {
$outputName = $_SERVER['argv'][1];
$output = $_SERVER['argv'][1];
} else {
$outputName = basename($filePath);
$output = basename($file);
}
/*--------------------------------------------------------------------------*/
require('../vendor/docdown/docdown.php');
// get package version
$version = json_decode(file_get_contents('../package.json'))->version;
// generate Markdown
$markdown = docdown(array(
'path' => '../' . $filePath,
'title' => 'Lo-Dash <span>v' . $version . '</span>',
'path' => '../' . $file,
'title' => 'Lo-Dash <sup>v1.3.0</sup>',
'toc' => 'categories',
'url' => 'https://github.com/lodash/lodash/blob/' . $version . '/lodash.js'
'url' => 'https://github.com/lodash/lodash/blob/1.3.0/lodash.js'
));
// save to a `.md` file
file_put_contents($outputName . '.md', $markdown);
// save to a .md file
file_put_contents($output . '.md', $markdown);
// print
header('Content-Type: text/plain;charset=utf-8');
echo $markdown . PHP_EOL;
?>

4921
lodash.js

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +1,58 @@
{
"name": "lodash",
"version": "2.3.0",
"description": "A utility library delivering consistency, customization, performance, & extras.",
"version": "1.3.0",
"description": "A low-level utility library delivering consistency, customization, performance, and extra features.",
"homepage": "http://lodash.com/",
"license": "MIT",
"main": "dist/lodash.js",
"keywords": ["amd", "browser", "client", "customize", "functional", "server", "util"],
"author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
"contributors": [
"John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
"Blaine Bublitz <blaine@iceddev.com> (http://www.iceddev.com/)",
"Kit Cambridge <github@kitcambridge.be> (http://kitcambridge.be/)",
"Mathias Bynens <mathias@qiwi.be> (http://mathiasbynens.be/)"
"main": "./dist/lodash.js",
"keywords": [
"browser",
"client",
"functional",
"performance",
"server",
"speed",
"util"
],
"bugs": "https://github.com/lodash/lodash/issues",
"repository": { "type": "git", "url": "https://github.com/lodash/lodash.git" },
"engines": ["node", "rhino"],
"files": [
"LICENSE.txt",
"lodash.js",
"dist/lodash.js",
"dist/lodash.min.js",
"dist/lodash.compat.js",
"dist/lodash.compat.min.js",
"dist/lodash.underscore.js",
"dist/lodash.underscore.min.js"
"author": {
"name": "John-David Dalton",
"email": "john.david.dalton@gmail.com",
"web": "http://allyoucanleet.com/"
},
"bugs": {
"url": "https://github.com/bestiejs/lodash/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/bestiejs/lodash.git"
},
"bin": {
"lodash": "./build.js"
},
"engines": [
"node",
"rhino"
],
"jam": {
"main": "dist/lodash.compat.js",
"include": [
"LICENSE.txt",
"dist/lodash.js",
"dist/lodash.min.js",
"dist/lodash.compat.js",
"dist/lodash.compat.min.js",
"dist/lodash.underscore.js",
"dist/lodash.underscore.min.js"
]
"main": "./dist/lodash.compat.js"
},
"volo": {
"type": "directory",
"ignore": [
".*",
"*.custom.*",
"*.min.*",
"*.template.*",
"*.d.ts",
"*.map",
"*.md",
"*.txt",
"build.js",
"lodash.js",
"index.js",
"bower.json",
"component.json",
"build",
"doc",
"modularize",
"node_modules",
"perf",
"test",

View File

@@ -32,7 +32,7 @@
<script src="../lodash.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 src="perf-ui.js"></script>
<script>
document.write('<script src="' + ui.buildPath + '"><\/script>');
</script>

View File

@@ -5,10 +5,10 @@
var basePath = '../';
/** The Lo-Dash build to load */
var build = (build = /build=([^&]+)/.exec(location.search)) && decodeURIComponent(build[1]);
var build = (/build=([^&]+)/.exec(location.search) || [])[1];
/** The other library to load */
var other = (other = /other=([^&]+)/.exec(location.search)) && decodeURIComponent(other[1]);
var other = (/other=([^&]+)/.exec(location.search) || [])[1];
/** The `ui` object */
var ui = {};
@@ -20,7 +20,7 @@
*
* @private
* @param {Element} element The element.
* @param {string} eventName The name of the event.
* @param {String} eventName The name of the event.
* @param {Function} handler The event handler.
* @returns {Element} The element.
*/
@@ -34,13 +34,46 @@
/*--------------------------------------------------------------------------*/
// expose Lo-Dash build file path
ui.buildPath = (function() {
var result;
switch (build) {
case 'lodash-compat': result = 'dist/lodash.compat.min.js'; break;
case 'lodash-legacy': result = 'dist/lodash.legacy.min.js'; break;
case 'lodash-mobile': result = 'dist/lodash.mobile.min.js'; break;
case 'lodash-underscore': result = 'dist/lodash.underscore.min.js'; break;
case 'lodash-custom-dev': result = 'lodash.custom.js'; break;
case 'lodash-custom': result = 'lodash.custom.min.js'; break;
case 'lodash-modern':
case undefined: result = 'dist/lodash.min.js'; break;
default: result = build;
}
return result == build ? result : (basePath + result);
}());
// expose other library file path
ui.otherPath = (function() {
var result;
switch (other) {
case 'lodash-compat': result = 'dist/lodash.compat.min.js'; break;
case 'lodash-legacy': result = 'dist/lodash.legacy.min.js'; break;
case 'lodash-mobile': result = 'dist/lodash.mobile.min.js'; break;
case 'lodash-modern': result = 'dist/lodash.min.js'; break;
case 'lodash-underscore': result = 'dist/lodash.underscore.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 'underscore':
case undefined: result = 'vendor/underscore/underscore-min.js'; break;
default: result = other;
}
return result == other ? result : (basePath + result);
}());
// initialize controls
addListener(window, 'load', function() {
function eventHandler(event) {
var buildIndex = buildList.selectedIndex,
otherIndex = otherList.selectedIndex,
search = location.search.replace(/^\?|&?(?:build|other)=[^&]*&?/g, '');
var search = location.search.replace(/^\?|&?(?:build|other)=[^&]*&?/g, '');
if (event.stopPropagation) {
event.stopPropagation();
} else {
@@ -49,8 +82,8 @@
location.href =
location.href.split('?')[0] + '?' +
(search ? search + '&' : '') +
'build=' + (buildIndex < 0 ? build : buildList[buildIndex].value) + '&' +
'other=' + (otherIndex < 0 ? other : otherList[otherIndex].value);
'build=' + buildList[buildList.selectedIndex].value + '&' +
'other=' + otherList[otherList.selectedIndex].value;
}
var span1 = document.createElement('span');
@@ -99,7 +132,7 @@
case 'lodash-custom-dev': return 5;
case 'lodash-custom': return 6;
case 'lodash-modern':
case null: return 3;
case undefined: return 3;
}
return -1;
}());
@@ -115,7 +148,7 @@
case 'lodash-custom-dev': return 7;
case 'lodash-custom': return 8;
case 'underscore':
case null: return 1;
case undefined: return 1;
}
return -1;
}());
@@ -124,48 +157,6 @@
addListener(otherList, 'change', eventHandler);
});
// expose Lo-Dash build file path
ui.buildPath = (function() {
var result;
switch (build) {
case 'lodash-compat': result = 'dist/lodash.compat.min.js'; break;
case 'lodash-legacy': result = 'dist/lodash.legacy.min.js'; break;
case 'lodash-mobile': result = 'dist/lodash.mobile.min.js'; break;
case 'lodash-underscore': result = 'dist/lodash.underscore.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 = 'dist/lodash.min.js'; break;
default: return build;
}
return basePath + result;
}());
// expose other library file path
ui.otherPath = (function() {
var result;
switch (other) {
case 'lodash-compat': result = 'dist/lodash.compat.min.js'; break;
case 'lodash-legacy': result = 'dist/lodash.legacy.min.js'; break;
case 'lodash-mobile': result = 'dist/lodash.mobile.min.js'; break;
case 'lodash-modern': result = 'dist/lodash.min.js'; break;
case 'lodash-underscore': result = 'dist/lodash.underscore.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;
default: return other;
}
return basePath + result;
}());
// expose `ui.urlParams` properties
ui.urlParams = {
'build': build,
'other': other
};
// expose `ui`
window.ui = ui;

View File

@@ -1,16 +1,16 @@
;(function(root) {
(function(window) {
/** Use a single "load" function */
var load = typeof require == 'function' ? require : root.load;
var load = typeof require == 'function' ? require : window.load;
/** The file path of the Lo-Dash file to test */
var filePath = (function() {
var min = 0;
var result = root.phantom
var result = window.phantom
? phantom.args
: (root.system
: (window.system
? (min = 1, system.args)
: (root.process ? (min = 2, process.argv) : (root.arguments || []))
: (window.process ? (min = 2, process.argv) : (window.arguments || []))
);
var last = result[result.length - 1];
@@ -26,22 +26,22 @@
}());
/** Load Lo-Dash */
var lodash = root.lodash || (root.lodash = (
lodash = load(filePath) || root._,
var lodash = window.lodash || (window.lodash = (
lodash = load(filePath) || window._,
lodash = lodash._ || lodash,
lodash.noConflict()
));
/** Load Benchmark.js */
var Benchmark = root.Benchmark || (root.Benchmark = (
Benchmark = load('../vendor/benchmark.js/benchmark.js') || root.Benchmark,
var Benchmark = window.Benchmark || (window.Benchmark = (
Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark,
Benchmark = Benchmark.Benchmark || Benchmark,
Benchmark.runInContext(lodash.extend({}, root, { '_': lodash }))
Benchmark.runInContext(lodash.extend({}, window, { '_': lodash }))
));
/** Load Underscore */
var _ = root._ || (root._ = (
_ = load('../vendor/underscore/underscore.js') || root._,
var _ = window._ || (window._ = (
_ = load('../vendor/underscore/underscore.js') || window._,
_._ || _
));
@@ -67,28 +67,25 @@
var toString = Object.prototype.toString;
/** The `ui` object */
var ui = root.ui || (root.ui = {
var ui = window.ui || (window.ui = {
'buildPath': basename(filePath, '.js'),
'otherPath': 'underscore'
});
/** The Lo-Dash build basename */
var buildName = root.buildName = basename(ui.buildPath, '.js');
var buildName = window.buildName = basename(ui.buildPath, '.js');
/** The other library basename */
var otherName = root.otherName = (function() {
var result = basename(ui.otherPath, '.js');
return result + (result == buildName ? ' (2)' : '');
}());
var otherName = window.otherName = basename(ui.otherPath, '.js');
/** Detect if in a browser environment */
var isBrowser = isHostType(root, 'document') && isHostType(root, 'navigator');
var isBrowser = isHostType(window, 'document') && isHostType(window, 'navigator');
/** Detect Java environment */
var isJava = !isBrowser && /Java/.test(toString.call(root.java));
var isJava = !isBrowser && /Java/.test(toString.call(window.java));
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
var console = root.console || (root.console = { 'log': root.print });
var console = window.console || (window.console = { 'log': window.print });
/*--------------------------------------------------------------------------*/
@@ -97,9 +94,9 @@
* it will be removed from the basename.
*
* @private
* @param {string} path The file path to inspect.
* @param {string} extension The extension to remove.
* @returns {string} Returns the basename.
* @param {String} path The file path to inspect.
* @param {String} extension The extension to remove.
* @returns {String} Returns the basename.
*/
function basename(filePath, extension) {
var result = (filePath || '').split(rePathSeparator).pop();
@@ -114,7 +111,7 @@
*
* @private
* @param {Array} array The array of values.
* @returns {number} The geometric mean.
* @returns {Number} The geometric mean.
*/
function getGeometricMean(array) {
return Math.pow(Math.E, lodash.reduce(array, function(sum, x) {
@@ -128,7 +125,7 @@
*
* @private
* @param {Object} bench The benchmark object.
* @returns {number} Returns the adjusted Hz.
* @returns {Number} Returns the adjusted Hz.
*/
function getHz(bench) {
var result = 1 / (bench.stats.mean + bench.stats.moe);
@@ -141,9 +138,9 @@
* types of "object", "function", or "unknown".
*
* @private
* @param {*} object The owner of the property.
* @param {string} property The property to check.
* @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
* @param {Mixed} object The owner of the property.
* @param {String} property The property to check.
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
*/
function isHostType(object, property) {
if (object == null) {
@@ -157,7 +154,7 @@
* Logs text to the console.
*
* @private
* @param {string} text The text to log.
* @param {String} text The text to log.
*/
function log(text) {
console.log(text + '');
@@ -173,7 +170,7 @@
* @private (@public in the browser)
*/
function run() {
fbPanel = (fbPanel = root.document && document.getElementById('FirebugUI')) &&
fbPanel = (fbPanel = window.document && document.getElementById('FirebugUI')) &&
(fbPanel = (fbPanel = fbPanel.contentWindow || fbPanel.contentDocument).document || fbPanel) &&
fbPanel.getElementById('fbPanel1');
@@ -257,8 +254,8 @@
lodash.extend(Benchmark.options, {
'async': true,
'setup': '\
var _ = global._,\
lodash = global.lodash,\
var _ = window._,\
lodash = window.lodash,\
belt = this.name == buildName ? lodash : _;\
\
var index,\
@@ -270,7 +267,6 @@
numbers = Array(limit),\
fourNumbers = [5, 25, 10, 30],\
nestedNumbers = [1, [2], [3, [[4]]]],\
nestedObjects = [{}, [{}], [{}, [[{}]]]],\
twoNumbers = [12, 23];\
\
for (index = 0; index < limit; index++) {\
@@ -280,24 +276,18 @@
}\
\
if (typeof bind != "undefined") {\
var thisArg = { "name": "fred" };\
var thisArg = { "name": "moe" },\
ctor = function() {};\
\
var func = function(greeting, punctuation) {\
return greeting + " " + this.name + (punctuation || ".");\
return greeting + ", " + this.name + (punctuation || ".");\
};\
\
var _boundNormal = _.bind(func, thisArg),\
_boundMultiple = _boundNormal,\
_boundPartial = _.bind(func, thisArg, "hi");\
\
var lodashBoundNormal = lodash.bind(func, thisArg),\
lodashBoundMultiple = lodashBoundNormal,\
lodashBoundPartial = lodash.bind(func, thisArg, "hi");\
\
for (index = 0; index < 10; index++) {\
_boundMultiple = _.bind(_boundMultiple, { "name": "fred" + index });\
lodashBoundMultiple = lodash.bind(lodashBoundMultiple, { "name": "fred" + index });\
}\
}\
\
if (typeof bindAll != "undefined") {\
@@ -482,15 +472,6 @@
}\
}\
\
if (typeof partial != "undefined") {\
var func = function(greeting, punctuation) {\
return greeting + " fred" + (punctuation || ".");\
};\
\
var _partial = _.partial(func, "hi"),\
lodashPartial = lodash.partial(func, "hi");\
}\
\
if (typeof template != "undefined") {\
var tplData = {\
"header1": "Header1",\
@@ -545,20 +526,9 @@
lodashFindWhere = lodash.findWhere || lodash.find,\
whereObject = { "num": 9 };\
}\
if (typeof wrap != "undefined") {\
var add = function(a, b) {\
return a + b;\
};\
\
var average = function(func, a, b) {\
return (func(a, b) / 2).toFixed(2);\
};\
\
var _wrapped = _.wrap(add, average);\
lodashWrapped = lodash.wrap(add, average);\
}\
if (typeof zip != "undefined") {\
var unzipped = [["a", "b", "c"], [1, 2, 3], [true, false, true]];\
var unzipped = [["a", "b", "c"], [1, 2, 3], [true, false, true]],\
zipped = [["a", 1, true], ["b", 2, false], ["c", 3, true]];\
}'
});
@@ -612,13 +582,25 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.bind`')
Benchmark.Suite('`_.bind` (uses native `Function#bind` if available and inferred fast)')
.add(buildName, {
'fn': 'lodash.bind(func, { "name": "fred" })',
'fn': 'lodash.bind(func, { "name": "moe" }, "hi")',
'teardown': 'function bind(){}'
})
.add(otherName, {
'fn': '_.bind(func, { "name": "fred" })',
'fn': '_.bind(func, { "name": "moe" }, "hi")',
'teardown': 'function bind(){}'
})
);
suites.push(
Benchmark.Suite('bound call')
.add(buildName, {
'fn': 'lodashBoundNormal()',
'teardown': 'function bind(){}'
})
.add(otherName, {
'fn': '_boundNormal()',
'teardown': 'function bind(){}'
})
);
@@ -636,7 +618,19 @@
);
suites.push(
Benchmark.Suite('bound and partially applied call with arguments')
Benchmark.Suite('bound and partially applied call (uses native `Function#bind` if available)')
.add(buildName, {
'fn': 'lodashBoundPartial()',
'teardown': 'function bind(){}'
})
.add(otherName, {
'fn': '_boundPartial()',
'teardown': 'function bind(){}'
})
);
suites.push(
Benchmark.Suite('bound and partially applied call with arguments (uses native `Function#bind` if available)')
.add(buildName, {
'fn': 'lodashBoundPartial("!")',
'teardown': 'function bind(){}'
@@ -647,18 +641,6 @@
})
);
suites.push(
Benchmark.Suite('bound multiple times')
.add(buildName, {
'fn': 'lodashBoundMultiple()',
'teardown': 'function bind(){}'
})
.add(otherName, {
'fn': '_boundMultiple()',
'teardown': 'function bind(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
@@ -716,20 +698,20 @@
suites.push(
Benchmark.Suite('`_.contains` iterating an array')
.add(buildName, '\
lodash.contains(numbers, limit - 1)'
lodash.contains(numbers, 19)'
)
.add(otherName, '\
_.contains(numbers, limit - 1)'
_.contains(numbers, 19)'
)
);
suites.push(
Benchmark.Suite('`_.contains` iterating an object')
.add(buildName, '\
lodash.contains(object, limit - 1)'
lodash.contains(object, 19)'
)
.add(otherName, '\
_.contains(object, limit - 1)'
_.contains(object, 19)'
)
);
@@ -971,12 +953,12 @@
Benchmark.Suite('`_.find` iterating an array')
.add(buildName, '\
lodash.find(numbers, function(num) {\
return num === (limit - 1);\
return num === 19;\
})'
)
.add(otherName, '\
_.find(numbers, function(num) {\
return num === (limit - 1);\
return num === 19;\
})'
)
);
@@ -1022,16 +1004,6 @@
)
);
suites.push(
Benchmark.Suite('`_.flatten` with objects')
.add(buildName, '\
lodash.flatten(nestedObjects)'
)
.add(otherName, '\
_.flatten(nestedObjects)'
)
);
suites.push(
Benchmark.Suite('`_.flatten` with `shallow`')
.add(buildName, '\
@@ -1092,49 +1064,13 @@
/*--------------------------------------------------------------------------*/
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, {
'fn': 'lodash.indexOf(twoHundredValues, 199)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
.add(buildName, {
'fn': '_.indexOf(twoHundredValues, 199)',
'teardown': 'function multiArrays(){}'
})
@@ -1462,32 +1398,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.partial`')
.add(buildName, {
'fn': 'lodash.partial(func, "hi")',
'teardown': 'function partial(){}'
})
.add(otherName, {
'fn': '_.partial(func, "hi")',
'teardown': 'function partial(){}'
})
);
suites.push(
Benchmark.Suite('partially applied call with arguments')
.add(buildName, {
'fn': 'lodashPartial("!")',
'teardown': 'function partial(){}'
})
.add(otherName, {
'fn': '_partial("!")',
'teardown': 'function partial(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.pick`')
.add(buildName, '\
@@ -1624,18 +1534,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.sample` with an `n`')
.add(buildName, '\
lodash.sample(numbers, limit / 2)'
)
.add(otherName, '\
_.sample(numbers, limit / 2)'
)
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.shuffle`')
.add(buildName, '\
@@ -1664,12 +1562,12 @@
Benchmark.Suite('`_.some` iterating an array')
.add(buildName, '\
lodash.some(numbers, function(num) {\
return num == (limit - 1);\
return num == 19;\
})'
)
.add(otherName, '\
_.some(numbers, function(num) {\
return num == (limit - 1);\
return num == 19;\
})'
)
);
@@ -1678,12 +1576,12 @@
Benchmark.Suite('`_.some` with `thisArg` iterating an array (slow path)')
.add(buildName, '\
lodash.some(objects, function(value, index) {\
return this["key" + index] == (limit - 1);\
return this["key" + index] == 19;\
}, object)'
)
.add(otherName, '\
_.some(objects, function(value, index) {\
return this["key" + index] == (limit - 1);\
return this["key" + index] == 19;\
}, object)'
)
);
@@ -1692,12 +1590,12 @@
Benchmark.Suite('`_.some` iterating an object')
.add(buildName, '\
lodash.some(object, function(num) {\
return num == (limit - 1);\
return num == 19;\
})'
)
.add(otherName, '\
_.some(object, function(num) {\
return num == (limit - 1);\
return num == 19;\
})'
)
);
@@ -1930,6 +1828,20 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.unzip`')
.add(buildName, {
'fn': 'lodash.unzip(zipped)',
'teardown': 'function zip(){}'
})
.add(otherName, {
'fn': '_.unzip(zipped)',
'teardown': 'function zip(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.values`')
.add(buildName, '\
@@ -1968,20 +1880,6 @@
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.wrap` result called')
.add(buildName, {
'fn': 'lodashWrapped(2, 5)',
'teardown': 'function wrap(){}'
})
.add(otherName, {
'fn': '_wrapped(2, 5)',
'teardown': 'function wrap(){}'
})
);
/*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_.zip`')
.add(buildName, {
@@ -2000,8 +1898,8 @@
log(Benchmark.platform);
}
// in the browser, expose `run` to be called later
if (root.document && !root.phantom) {
root.run = run;
if (window.document && !window.phantom) {
window.run = run;
} else {
run();
}

View File

@@ -1,174 +0,0 @@
;(function(window) {
'use strict';
/** The base path of the builds */
var basePath = '../';
/** The Lo-Dash build to load */
var build = (build = /build=([^&]+)/.exec(location.search)) && decodeURIComponent(build[1]);
/** The module loader to use */
var loader = (loader = /loader=([^&]+)/.exec(location.search)) && decodeURIComponent(loader[1]);
/** The `ui` object */
var ui = {};
/*--------------------------------------------------------------------------*/
/**
* 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
addListener(window, 'load', function() {
function eventHandler(event) {
var buildIndex = buildList.selectedIndex,
loaderIndex = loaderList.selectedIndex,
search = location.search.replace(/^\?|&?(?:build|loader)=[^&]*&?/g, '');
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
location.href =
location.href.split('?')[0] + '?' +
(search ? search + '&' : '') +
'build=' + (buildIndex < 0 ? build : buildList[buildIndex].value) + '&' +
'loader=' + (loaderIndex < 0 ? loader : loaderList[loaderIndex].value);
}
function init() {
var toolbar = document.getElementById('qunit-testrunner-toolbar');
if (toolbar) {
toolbar.appendChild(span1);
toolbar.appendChild(span2);
buildList.selectedIndex = (function() {
switch (build) {
case 'lodash-compat': return 1;
case 'lodash-modern-dev': return 2;
case 'lodash-modern': return 3;
case 'lodash-legacy': return 4;
case 'lodash-mobile': return 5;
case 'lodash-underscore': return 6;
case 'lodash-custom-dev': return 7;
case 'lodash-custom': return 8;
case 'lodash-compat-dev':
case null: return 0;
}
return -1;
}());
loaderList.selectedIndex = (function() {
switch (loader) {
case 'curl': return 1;
case 'dojo': return 2;
case 'requirejs': return 3;
case 'none':
case null: return 0;
}
return -1;
}());
addListener(buildList, 'change', eventHandler);
addListener(loaderList, 'change', eventHandler);
}
else {
setTimeout(init, 15);
}
}
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-compat-dev">Lo-Dash (compat development)</option>' +
'<option value="lodash-compat">Lo-Dash (compat production)</option>' +
'<option value="lodash-modern-dev">Lo-Dash (modern development)</option>' +
'<option value="lodash-modern">Lo-Dash (modern production)</option>' +
'<option value="lodash-legacy">Lo-Dash (legacy)</option>' +
'<option value="lodash-mobile">Lo-Dash (mobile)</option>' +
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
'<option value="lodash-custom-dev">Lo-Dash (custom development)</option>' +
'<option value="lodash-custom">Lo-Dash (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">' +
'<option value="none">None</option>' +
'<option value="curl">Curl</option>' +
'<option value="dojo">Dojo</option>' +
'<option value="requirejs">RequireJS</option>' +
'</select>';
var buildList = span1.lastChild,
loaderList = span2.lastChild;
init();
});
// expose Lo-Dash build file path
ui.buildPath = (function() {
var result;
switch (build) {
case 'lodash-compat': result = 'dist/lodash.compat.min.js'; break;
case 'lodash-modern-dev': result = 'dist/lodash.js'; break;
case 'lodash-modern': result = 'dist/lodash.min.js'; break;
case 'lodash-legacy': result = 'dist/lodash.legacy.min.js'; break;
case 'lodash-mobile': result = 'dist/lodash.mobile.min.js'; break;
case 'lodash-underscore': result = 'dist/lodash.underscore.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.js'; break;
default: return build;
}
return basePath + result;
}());
// expose module loader file path
ui.loaderPath = (function() {
var result;
switch (loader) {
case 'curl': result = 'vendor/curl/dist/curl-kitchen-sink/curl.js'; break;
case 'dojo': result = 'vendor/dojo/dojo.js'; break;
case 'requirejs': result = 'vendor/requirejs/require.js'; break;
case null: loader = 'none'; return '';
default: return loader;
}
return basePath + result;
}());
// expose `ui.urlParams` properties
ui.urlParams = {
'build': build,
'loader': loader
};
// used to indicate testing a modularized build
ui.isModularize = /\b(?:commonjs|(index|main)\.js|lodash-(?:amd|node)|modularize|npm)\b/.test([location.pathname, location.search, ui.buildPath]);
// expose `ui`
window.ui = ui;
}(this));

View File

@@ -1,6 +0,0 @@
addEventListener('message', function(e) {
if (e.data) {
importScripts('../' + e.data);
postMessage(_.VERSION);
}
}, false);

View File

@@ -18,87 +18,20 @@
<h1>Test</h1>
</div>
</div>
<script src="../vendor/json-js/json2.js"></script>
<script src="../vendor/json3/lib/json3.js"></script>
<script src="../vendor/jquery/jquery.js"></script>
<script src="../vendor/platform.js/platform.js"></script>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="./asset/test-ui.js"></script>
<script src="test-ui.js"></script>
<script src="../lodash.js"></script>
<script>
var lodash = _.noConflict();
QUnit.config.hidepassed = true;
// assign results to `global_test_results` for Sauce Labs
var global_test_results;
QUnit.done(function(results) {
global_test_results = results;
});
// skip tests we intentionally fail or those with problems
(function() {
var skipped = {
'Backbone.Collection': {
'set with many models does not overflow the stack': true
},
'Backbone.Router': {
'#2656 - No trailing slash on root.': true,
'#2765 - Fragment matching sans query/hash.': true
}
};
// only skip `Backbone.Router` tests in IE < 8
if (!(document.attachEvent && (document.documentMode || 0) < 8)) {
delete skipped['Backbone.Router'];
}
QUnit.testStart(function(details) {
var test = QUnit.config.current,
finish = test.finish,
skippedTests = skipped[details.module],
skippedAsserts = skippedTests && skippedTests[details.name];
if (!skippedAsserts) {
return;
}
if (skippedAsserts === true) {
test.async = false;
test.callback = function() {};
test.expected = 0;
return;
}
test.finish = function() {
var index = -1,
asserts = this.assertions,
length = asserts.length;
while (++index < length) {
var assert = asserts[index],
message = _.unescape(_.result(/^<span class='test-message'>([\s\S]*?)<\/span>/.exec(assert.message), 1)),
died = _.result(/^Died on test #\d+/.exec(message), 0),
expected = _.unescape(_.result(/Expected: *<\/th><td><pre>([\s\S]*?)<\/pre>/.exec(assert.message), 1));
if ((message && _.contains(skippedAsserts, message)) ||
(died && _.contains(skippedAsserts, died)) ||
(expected && (_.contains(skippedAsserts, expected) ||
_.contains(skippedAsserts, expected.replace(/\s+/g, '')))
)) {
assert.result = true;
}
}
finish.call(this);
};
});
}());
// load Lo-Dash again to overwrite the existing `_` value
document.write('<script src="' + ui.buildPath + '"><\/script>');
document.write('<script src="../' + ui.buildPath + '"><\/script>');
</script>
<script>
_.mixin({
'debounce': _.debounce || lodash.debounce,
'defer': _.defer || lodash.defer,
'pluck': _.pluck || lodash.pluck
'debounce': lodash.debounce,
'defer': lodash.defer
});
</script>
<script src="../vendor/backbone/backbone.js"></script>

View File

@@ -13,160 +13,73 @@
<body>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="../vendor/platform.js/platform.js"></script>
<script src="./asset/test-ui.js"></script>
<script src="test-ui.js"></script>
<div id="qunit"></div>
<div id="exports"></div>
<script>
// set bad shims
Array._isArray = Array.isArray;
Array.isArray = function() { return false; };
Function.prototype._bind = Function.prototype.bind;
Function.prototype.bind = function() { return function() {}; };
Object._create = Object.create;
Object.create = function() {};
Object._defineProperty = Object.defineProperty;
Object.defineProperty = function() {};
// set a bad shim
Object._keys = Object.keys;
Object.keys = function() { return []; };
// load Lo-Dash and expose it to the bad `Object.keys` shim
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
document.write('<script src="../' + ui.buildPath + '"><\/script>');
</script>
<script>
// store Lo-Dash to test for bad shim detection
var lodashBadShim = window._;
var lodashBadShim = _;
// restore native methods
if (Array._isArray) {
Array.isArray = Array._isArray;
} else {
delete Array.isArray;
}
if (Function.prototype._bind) {
Function.prototype.bind = Function.prototype._bind;
} else {
delete Function.prototype.bind;
}
if (Object._create) {
Object.create = Object._create;
} else {
delete Object.create;
}
if (Object._defineProperty) {
Object.defineProperty = Object._defineProperty;
} else {
delete Object.defineProperty;
}
if (Object._keys) {
Object.keys = Object._keys;
} else {
delete Object.keys;
}
delete Array._isArray;
delete Function.prototype._bind;
delete Object._create;
delete Object._defineProperty;
// restore nativeKeys
Object.keys = Object._keys;
delete Object._keys;
QUnit.config.hidepassed = true;
// assign results to `global_test_results` for Sauce Labs
var global_test_results;
QUnit.done(function(results) {
global_test_results = results;
});
// load Lo-Dash again to overwrite the existing `_` value
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
document.write('<script src="../' + ui.buildPath + '"><\/script>');
// load test.js if not using require.js
document.write(ui.urlParams.loader == 'none'
document.write(QUnit.urlParams.norequire
? '<script src="test.js"><\/script>'
: '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
: '<script src="../vendor/requirejs/require.js"><\/script>'
);
</script>
<script>
// load Lo-Dash as a module
var lodashModule,
shimmedModule,
underscoreModule;
window.require && require(
(function() {
if (window.curl) {
curl.config({ 'apiName': 'require' });
}
if (!window.require) {
return;
}
var reBasename = /[\w.-]+$/,
basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''),
modulePath = ui.buildPath.replace(/\.js$/, ''),
locationPath = modulePath.replace(reBasename, ''),
moduleMain = modulePath.match(reBasename)[0];
QUnit.config.autostart = false;
// load Lo-Dash as a module
require({
'baseUrl': './',
var modulePath = ui.buildPath.replace(/\.js$/, '');
return {
'baseUrl': '../vendor/requirejs/',
'urlArgs': 't=' + (+new Date),
'packages': [
{
'name': 'lodash',
'location': locationPath,
'main': moduleMain
},
{
'name': 'shimmed',
'location': './abc/../' + locationPath,
'main': moduleMain
},
{
'name': 'underscore',
'location': './xyz/../' + locationPath,
'main': moduleMain
},
{
'name': 'test',
'location': basePath + '/test',
'main': 'test',
'config': {
// work around no global being exported
'exports': 'QUnit',
'loader': 'curl/loader/legacy'
}
}
],
'paths': {
'lodash': '../../' + modulePath,
'shimmed': './../../' + modulePath,
'underscore': '../underscore/../../' + modulePath
},
'shim': {
'shimmed': {
'exports': '_'
'exports': '_'
}
}
},
['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) {
if (shimmed && shimmed.noConflict) {
shimmedModule = shimmed.noConflict();
shimmedModule.moduleName = 'shimmed';
}
if (underscore && underscore.noConflict) {
underscoreModule = underscore.noConflict();
underscoreModule.moduleName = 'underscore';
}
if (lodash && lodash.noConflict) {
lodashModule = lodash.noConflict();
lodashModule.moduleName = 'lodash';
}
if (ui.isModularize) {
window._ = lodash;
}
require(['test'], function() {
QUnit.start();
});
});
}());
};
}()),
['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) {
if (lodash && lodash.noConflict) {
lodashModule = lodash.noConflict();
lodashModule.moduleName = 'lodash';
}
if (shimmed.noConflict) {
shimmedModule = shimmed.noConflict();
shimmedModule.moduleName = 'shimmed';
}
if (underscore && underscore.noConflict) {
underscoreModule = underscore.noConflict();
underscoreModule.moduleName = 'underscore';
}
require(['test.js']);
});
// set a more readable browser name
window.onload = function() {
@@ -176,7 +89,7 @@
ua.innerHTML = platform;
clearInterval(timeoutId);
}
}, 16);
}, 15);
};
</script>
</body>

View File

@@ -9,6 +9,10 @@ done
echo "Testing in node..."
node test.js ../dist/lodash.js && node test.js ../dist/lodash.min.js
echo ""
echo "Testing build..."
node test-build.js
echo ""
echo "Testing in a browser..."
open index.html

View File

@@ -1,232 +0,0 @@
;(function() {
'use strict';
var ecstatic = require('ecstatic'),
http = require('http'),
path = require('path'),
request = require('request'),
SauceTunnel = require('sauce-tunnel'),
url = require('url');
var attempts = -1,
prevLine = '';
var port = 8081,
username = process.env.SAUCE_USERNAME,
accessKey = process.env.SAUCE_ACCESS_KEY,
tunnelId = 'lodash_' + process.env.TRAVIS_JOB_NUMBER;
if (isFinite(process.env.TRAVIS_PULL_REQUEST)) {
console.error('Testing skipped for pull requests');
process.exit(0);
}
var runnerPathname = (function() {
var args = process.argv;
return args.length > 2
? '/' + args[args.length - 1].replace(/^\W+/, '')
: '/test/index.html';
}());
var runnerQuery = url.parse(runnerPathname, true).query,
isBackbone = /\bbackbone\b/i.test(runnerPathname),
isMobile = /\bmobile\b/i.test(runnerQuery.build),
isModern = /\bmodern\b/i.test(runnerQuery.build);
var platforms = [
['Windows 7', 'chrome', ''],
['Windows 7', 'firefox', '25'],
['Windows 7', 'firefox', '20'],
['Windows 7', 'firefox', '10'],
['Windows 7', 'firefox', '6'],
['Windows 7', 'firefox', '4'],
['Windows 7', 'firefox', '3'],
['WIN8.1', 'internet explorer', '11'],
['Windows 7', 'internet explorer', '10'],
['Windows 7', 'internet explorer', '9'],
['Windows 7', 'internet explorer', '8'],
['Windows XP', 'internet explorer', '7'],
['Windows XP', 'internet explorer', '6'],
//['Windows 7', 'opera', '12'],
//['Windows 7', 'opera', '11'],
['OS X 10.8', 'safari', '6'],
['Windows 7', 'safari', '5']
];
// platforms to test IE compat mode
if (runnerQuery.compat) {
platforms = [
['WIN8.1', 'internet explorer', '11'],
['Windows 7', 'internet explorer', '10'],
['Windows 7', 'internet explorer', '9'],
['Windows 7', 'internet explorer', '8']
];
}
// platforms for Backbone tests
if (isBackbone) {
platforms = platforms.filter(function(platform) {
var browser = platform[1],
version = +platform[2];
switch (browser) {
case 'firefox': return version >= 4;
case 'opera': return version >= 12;
}
return true;
});
}
// platforms for mobile and modern builds
if (isMobile || isModern) {
platforms = platforms.filter(function(platform) {
var browser = platform[1],
version = +platform[2];
switch (browser) {
case 'firefox': return version >= 10;
case 'internet explorer': return version >= 9;
case 'opera': return version >= 12;
case 'safari': return version >= (isMobile ? 5 : 6);
}
return true;
});
}
// create a web server for the local dir
var mount = ecstatic({
'root': process.cwd(),
'cache': false
});
http.createServer(function(req, res) {
var compat = url.parse(req.url, true).query.compat;
if (compat) {
// see http://msdn.microsoft.com/en-us/library/ff955275(v=vs.85).aspx
res.setHeader('X-UA-Compatible', 'IE=' + compat);
}
mount(req, res);
}).listen(port);
// set up Sauce Connect so we can use this server from Sauce Labs
var tunnelTimeout = 10000,
tunnel = new SauceTunnel(username, accessKey, tunnelId, true, tunnelTimeout);
console.log('Opening Sauce Connect tunnel...');
tunnel.start(function(success) {
if (success) {
console.log('Sauce Connect tunnel opened');
runTests();
} else {
console.error('Failed to open Sauce Connect tunnel');
process.exit(2);
}
});
/*--------------------------------------------------------------------------*/
function logInline(text) {
var blankLine = repeat(' ', prevLine.length);
if (text.length > 40) {
text = text.slice(0, 37) + '...';
}
prevLine = text;
process.stdout.write(text + blankLine.slice(text.length) + '\r');
}
function repeat(text, times) {
return Array(times + 1).join(text);
}
/*--------------------------------------------------------------------------*/
function runTests() {
var testDefinition = {
'framework': 'qunit',
'platforms': platforms,
'tunnel': 'tunnel-identifier:' + tunnelId,
'url': 'http://localhost:' + port + runnerPathname
};
console.log('Starting saucelabs tests: ' + JSON.stringify(testDefinition));
request.post('https://saucelabs.com/rest/v1/' + username + '/js-tests', {
'auth': { 'user': username, 'pass': accessKey },
'json': testDefinition
}, function(error, response, body) {
var statusCode = response && response.statusCode;
if (statusCode == 200) {
waitForTestCompletion(body);
} else {
console.error('Failed to submit test to Sauce Labs; status: ' + statusCode + ', body:\n' + JSON.stringify(body));
if (error) {
console.error(error);
}
process.exit(3);
}
});
}
function waitForTestCompletion(testIdentifier) {
request.post('https://saucelabs.com/rest/v1/' + username + '/js-tests/status', {
'auth': { 'user': username, 'pass': accessKey },
'json': testIdentifier
}, function(error, response, body) {
var statusCode = response && response.statusCode;
if (statusCode == 200) {
if (body.completed) {
logInline('');
handleTestResults(body['js tests']);
}
else {
logInline('Please wait' + repeat('.', (++attempts % 3) + 1));
setTimeout(function() {
waitForTestCompletion(testIdentifier);
}, 5000);
}
} else {
logInline('');
console.error('Failed to check test status on Sauce Labs; status: ' + statusCode + ', body:\n' + JSON.stringify(body));
if (error) {
console.error(error);
}
process.exit(4);
}
});
}
function handleTestResults(results) {
var failingTests = results.filter(function(test) {
var result = test.result;
return !result || result.failed || /\berror\b/i.test(result.message);
});
var failingPlatforms = failingTests.map(function(test) {
return test.platform;
});
if (!failingTests.length) {
console.log('Tests passed');
}
else {
console.error('Tests failed on platforms: ' + JSON.stringify(failingPlatforms));
failingTests.forEach(function(test) {
var details = 'See ' + test.url + ' for details.',
platform = JSON.stringify(test.platform),
result = test.result;
if (result && result.failed) {
console.error(result.failed + ' failures on ' + platform + '. ' + details);
} else {
console.error('Testing on ' + platform + ' failed; no results available. ' + details);
}
});
}
console.log('Shutting down Sauce Connect tunnel...');
tunnel.stop(function() {
process.exit(failingTests.length ? 1 : 0);
});
}
}());

3
test/template/a.jst Normal file
View File

@@ -0,0 +1,3 @@
<ul>
<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
</ul>

1
test/template/b.jst Normal file
View File

@@ -0,0 +1 @@
<% print("Hello " + epithet); %>.

1
test/template/c.jst Normal file
View File

@@ -0,0 +1 @@
Hello ${ name }!

1
test/template/d.tpl Normal file
View File

@@ -0,0 +1 @@
Hallå {{ name }}!

1707
test/test-build.js Normal file

File diff suppressed because it is too large Load Diff

114
test/test-ui.js Normal file
View File

@@ -0,0 +1,114 @@
;(function(window) {
'use strict';
/** `QUnit.addEvent` shortcut */
var addEvent = QUnit.addEvent;
/** The Lo-Dash build to load */
var build = (/build=([^&]+)/.exec(location.search) || [])[1];
/** A flag to determine if RequireJS should be loaded */
var norequire = /[?&]norequire=true(?:&|$)/.test(location.search);
/** The `ui` object */
var ui = {};
/*--------------------------------------------------------------------------*/
// expose Lo-Dash build file path
ui.buildPath = (function() {
switch (build) {
case 'lodash-compat': return 'dist/lodash.compat.min.js';
case 'lodash-modern-dev': return 'dist/lodash.js';
case 'lodash-modern': return 'dist/lodash.min.js';
case 'lodash-legacy': return 'dist/lodash.legacy.min.js';
case 'lodash-mobile': return 'dist/lodash.mobile.min.js';
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
case 'lodash-custom-dev': return 'lodash.custom.js';
case 'lodash-custom': return 'lodash.custom.min.js';
}
return 'lodash.js';
}());
// assign `QUnit.urlParams` properties
QUnit.extend(QUnit.urlParams, {
'build': build,
'norequire': norequire
});
// initialize controls
addEvent(window, 'load', function() {
function eventHandler(event) {
var search = location.search.replace(/^\?|&?(?:build|norequire)=[^&]*&?/g, '');
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
location.href =
location.href.split('?')[0] + '?' +
(search ? search + '&' : '') +
'build=' + buildList[buildList.selectedIndex].value +
(checkbox.checked ? '&norequire=true' : '');
}
function init() {
var toolbar = document.getElementById('qunit-testrunner-toolbar');
if (toolbar) {
toolbar.appendChild(span1);
toolbar.appendChild(span2);
buildList.selectedIndex = (function() {
switch (build) {
case 'lodash-compat': return 1;
case 'lodash-modern-dev': return 2;
case 'lodash-modern': return 3;
case 'lodash-legacy': return 4;
case 'lodash-mobile': return 5;
case 'lodash-underscore': return 6;
case 'lodash-custom-dev': return 7;
case 'lodash-custom': return 8;
}
return 0;
}());
checkbox.checked = norequire;
addEvent(checkbox, 'click', eventHandler);
addEvent(buildList, 'change', eventHandler);
}
else {
setTimeout(init, 15);
}
}
var span1 = document.createElement('span');
span1.innerHTML =
'<input id="qunit-norequire" type="checkbox">' +
'<label for="qunit-norequire">No RequireJS</label>';
var span2 = document.createElement('span');
span2.style.cssText = 'float:right';
span2.innerHTML =
'<label for="qunit-build">Build: </label>' +
'<select id="qunit-build">' +
'<option value="lodash-compat-dev">Lo-Dash (compat development)</option>' +
'<option value="lodash-compat">Lo-Dash (compat production)</option>' +
'<option value="lodash-modern-dev">Lo-Dash (modern development)</option>' +
'<option value="lodash-modern">Lo-Dash (modern production)</option>' +
'<option value="lodash-legacy">Lo-Dash (legacy)</option>' +
'<option value="lodash-mobile">Lo-Dash (mobile)</option>' +
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
'<option value="lodash-custom-dev">Lo-Dash (custom development)</option>' +
'<option value="lodash-custom">Lo-Dash (custom production)</option>' +
'</select>';
var checkbox = span1.firstChild,
buildList = span2.lastChild;
init();
});
// expose `ui`
window.ui = ui;
}(this));

File diff suppressed because it is too large Load Diff

View File

@@ -19,223 +19,79 @@
</div>
<img id="chart_image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
</div>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="../vendor/jquery/jquery.js"></script>
<script src="../vendor/platform.js/platform.js"></script>
<script src="./asset/test-ui.js"></script>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="test-ui.js"></script>
<script>
QUnit.config.hidepassed = true;
// assign results to `global_test_results` for Sauce Labs
var global_test_results;
QUnit.done(function(results) {
global_test_results = results;
});
// skip tests we intentionally fail or those with problems
(function() {
var skipped = {
'Arrays': {
'union': [
'[null,1,2,3]'
]
},
'Chaining': {
'reverse/concat/unshift/pop/map': [
'"34, 10, 8, 6, 4, 2, 10, 10"'
]
},
'Collections': {
'reduce': [
'handles a null (without initial value) properly',
'throws an error for empty arrays with no initial value'
],
'reduceRight': [
'handles a null (without initial value) properly',
'throws an error for empty arrays with no initial value'
],
'where': [
'Only get the first object matched.'
]
},
'Functions': {
'bind': [
'can bind without specifying a context',
'Died on test #2'
],
'bindAll': [
'throws an error for bindAll with no functions named'
],
'throttle': true,
'throttle arguments': true,
'throttle once': true,
'throttle twice': true,
'more throttling': true,
'throttle repeatedly with results': true,
'throttle triggers trailing call when invoked repeatedly': true,
'throttle does not trigger leading call when leading is set to false': 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': true,
'debounce asap': true,
'debounce asap recursively': true
},
'Objects': {
'isEqual': [
'Died on test #78'
],
'keys': [
'throws an error for `null` values',
'throws an error for `undefined` values',
'throws an error for number primitives',
'throws an error for string primitives',
'throws an error for boolean primitives'
]
},
'Utility': {
'_.escape': [
'"&lt;a href=&quot;http://moe.com&quot;&gt;Curly &amp; Moe&#x27;s&lt;/a&gt;"'
],
'_.unescape': [
'"<a href=\\"http://moe.com\\">Curly & Moe&#039;s</a>"'
],
'times': [
'Died on test #1'
],
'uniqueId': [
'Died on test #1'
]
}
};
// only skip in non-Underscore builds
if (/\bunderscore\b/i.test(ui.buildPath)) {
delete skipped.Chaining;
delete skipped.Collections.where;
delete skipped.Utility['_.escape'];
delete skipped.Utility['_.unescape'];
}
// only skip in Sauce Labs
if (location.port != '8081') {
for (var key in skipped.Functions) {
if (/\b(debounce|throttl)/.test(key)) {
delete skipped.Functions[key];
}
}
delete skipped.Objects.isEqual;
delete skipped.Utility.times;
delete skipped.Utility.uniqueId;
}
QUnit.testStart(function(details) {
var test = QUnit.config.current,
finish = test.finish,
skippedTests = skipped[details.module],
skippedAsserts = skippedTests && skippedTests[details.name];
if (!skippedAsserts) {
return;
}
if (skippedAsserts === true) {
test.async = false;
test.callback = function() {};
test.expected = 0;
return;
}
test.finish = function() {
var index = -1,
asserts = this.assertions,
length = asserts.length;
while (++index < length) {
var assert = asserts[index],
message = _.unescape(_.result(/^<span class='test-message'>([\s\S]*?)<\/span>/.exec(assert.message), 1)),
died = _.result(/^Died on test #\d+/.exec(message), 0),
expected = _.unescape(_.result(/Expected: *<\/th><td><pre>([\s\S]*?)<\/pre>/.exec(assert.message), 1));
if ((message && _.contains(skippedAsserts, message)) ||
(died && _.contains(skippedAsserts, died)) ||
(expected && (_.contains(skippedAsserts, expected) ||
_.contains(skippedAsserts, expected.replace(/\s+/g, '')))
)) {
assert.result = true;
}
}
finish.call(this);
};
});
}());
// load Lo-Dash again to overwrite the existing `_` value
document.write('<script src="' + (ui.isModularize ? '../lodash.js' : ui.buildPath) + '"><\/script>');
// load test.js if not using require.js
document.write(ui.urlParams.loader != 'none'
? '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/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>',
'<script src="../vendor/underscore/test/objects.js"><\/script>',
'<script src="../vendor/underscore/test/utility.js"><\/script>',
'<script src="../vendor/underscore/test/chaining.js"><\/script>'
].join('\n'))
);
document.write('<script src="../' + ui.buildPath + '"><\/script>');
</script>
<script>
(function() {
if (window.curl) {
curl.config({ 'apiName': 'require' });
}
if (!window.require) {
var arrayProto = Array.prototype,
concat = arrayProto.concat,
pop = arrayProto.pop,
push = arrayProto.push,
slice = arrayProto.slice;
if (_.chain().__chain__) {
return;
}
var reBasename = /[\w.-]+$/,
basePath = ('//' + location.host + location.pathname).replace(/\btest\/$/, ''),
modulePath = ui.buildPath.replace(/\.js$/, ''),
locationPath = modulePath.replace(reBasename, ''),
moduleMain = modulePath.match(reBasename)[0];
_.mixin = function(object) {
_.forEach(_.functions(object), function(methodName) {
var func = _[methodName] = object[methodName];
_.prototype[methodName] = function() {
var args = [this.__wrapped__];
push.apply(args, arguments);
QUnit.config.autostart = false;
// load Lo-Dash as a module
require({
'baseUrl': './',
'urlArgs': 't=' + (+new Date),
'packages': [
{
'name': 'lodash',
'location': locationPath,
'main': moduleMain
},
{
'name': 'test',
'location': '../vendor/underscore/test',
'config': {
// work around no global being exported
'exports': 'QUnit',
'loader': 'curl/loader/legacy'
var result = func.apply(_, args);
if (this.__chain__) {
result = new _(result);
result.__chain__ = true;
}
}
]
},
['lodash'], function(lodash) {
if (ui.isModularize) {
window._ = lodash;
}
require([
'test/collections',
'test/arrays',
'test/functions',
'test/objects',
'test/utility',
'test/chaining'
], function() {
QUnit.start();
return result;
};
});
};
_.mixin(_);
_.mixin({
'findWhere': _.find
});
_.chain = function(value) {
value = new _(value);
value.__chain__ = true;
return value;
};
_.prototype.chain = function() {
this.__chain__ = true;
return this;
};
_.prototype.concat = function() {
var result = concat.apply(this.__wrapped__, arguments);
if (this.__chain__) {
result = new _(result);
result.__chain__ = true;
}
return result;
};
_.prototype.pop = function() {
pop.apply(this.__wrapped__, arguments);
return this;
};
}());
</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>
<script src="../vendor/underscore/test/objects.js"></script>
<script src="../vendor/underscore/test/utility.js"></script>
<script src="../vendor/underscore/test/chaining.js"></script>
<script type="text/html" id="template">
<%
// a comment

26
vendor/backbone/README.md vendored Normal file
View File

@@ -0,0 +1,26 @@
____ __ __
/\ _`\ /\ \ /\ \ __
\ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____
\ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\
\ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\
\ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/
\/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/
\ \____/
\/___/
(_'_______________________________________________________________________________'_)
(_.———————————————————————————————————————————————————————————————————————————————._)
Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.
For Docs, License, Tests, pre-packed downloads, and everything else, really, see:
http://backbonejs.org
To suggest a feature, report a bug, or general discussion:
http://github.com/documentcloud/backbone/issues/
All contributors are listed here:
http://github.com/documentcloud/backbone/contributors
Special thanks to Robert Kieffer for the original philosophy behind Backbone.
http://github.com/broofa

View File

@@ -1,7 +1,6 @@
// Backbone.js 1.1.0
// Backbone.js 1.0.0
// (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
// (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2010-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
@@ -35,7 +34,7 @@
}
// Current version of the library. Keep in sync with `package.json`.
Backbone.VERSION = '1.1.0';
Backbone.VERSION = '1.0.0';
// Require Underscore, if we're on the server, and it's not already present.
var _ = root._;
@@ -53,7 +52,7 @@
};
// Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
// will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
// will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and
// set a `X-Http-Method-Override` header.
Backbone.emulateHTTP = false;
@@ -112,6 +111,7 @@
this._events = {};
return this;
}
names = name ? [name] : _.keys(this._events);
for (i = 0, l = names.length; i < l; i++) {
name = names[i];
@@ -151,15 +151,14 @@
// Tell this object to stop listening to either specific events ... or
// to every object it's currently listening to.
stopListening: function(obj, name, callback) {
var listeningTo = this._listeningTo;
if (!listeningTo) return this;
var remove = !name && !callback;
if (!callback && typeof name === 'object') callback = this;
if (obj) (listeningTo = {})[obj._listenId] = obj;
for (var id in listeningTo) {
obj = listeningTo[id];
obj.off(name, callback, this);
if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
var listeners = this._listeners;
if (!listeners) return this;
var deleteListener = !name && !callback;
if (typeof name === 'object') callback = this;
if (obj) (listeners = {})[obj._listenerId] = obj;
for (var id in listeners) {
listeners[id].off(name, callback, this);
if (deleteListener) delete this._listeners[id];
}
return this;
}
@@ -216,10 +215,10 @@
// listening to.
_.each(listenMethods, function(implementation, method) {
Events[method] = function(obj, name, callback) {
var listeningTo = this._listeningTo || (this._listeningTo = {});
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
listeningTo[id] = obj;
if (!callback && typeof name === 'object') callback = this;
var listeners = this._listeners || (this._listeners = {});
var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));
listeners[id] = obj;
if (typeof name === 'object') callback = this;
obj[implementation](name, callback, this);
return this;
};
@@ -244,18 +243,24 @@
// Create a new model with the specified attributes. A client id (`cid`)
// is automatically generated and assigned for you.
var Model = Backbone.Model = function(attributes, options) {
var defaults;
var attrs = attributes || {};
options || (options = {});
this.cid = _.uniqueId('c');
this.attributes = {};
if (options.collection) this.collection = options.collection;
_.extend(this, _.pick(options, modelOptions));
if (options.parse) attrs = this.parse(attrs, options) || {};
attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
if (defaults = _.result(this, 'defaults')) {
attrs = _.defaults({}, attrs, defaults);
}
this.set(attrs, options);
this.changed = {};
this.initialize.apply(this, arguments);
};
// A list of options to be attached directly to the model, if provided.
var modelOptions = ['url', 'urlRoot', 'collection'];
// Attach all inheritable methods to the Model prototype.
_.extend(Model.prototype, Events, {
@@ -451,16 +456,13 @@
(attrs = {})[key] = val;
}
// If we're not waiting and attributes exist, save acts as `set(attr).save(null, opts)`.
if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false;
options = _.extend({validate: true}, options);
// If we're not waiting and attributes exist, save acts as
// `set(attr).save(null, opts)` with validation. Otherwise, check if
// the model will be valid when the attributes, if any, are set.
if (attrs && !options.wait) {
if (!this.set(attrs, options)) return false;
} else {
if (!this._validate(attrs, options)) return false;
}
// Do not persist invalid models.
if (!this._validate(attrs, options)) return false;
// Set temporary attributes if `{wait: true}`.
if (attrs && options.wait) {
@@ -561,7 +563,7 @@
attrs = _.extend({}, this.attributes, attrs);
var error = this.validationError = this.validate(attrs, options) || null;
if (!error) return true;
this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
this.trigger('invalid', this, error, _.extend(options || {}, {validationError: error}));
return false;
}
@@ -594,6 +596,7 @@
// its models in sort order, as they're added and removed.
var Collection = Backbone.Collection = function(models, options) {
options || (options = {});
if (options.url) this.url = options.url;
if (options.model) this.model = options.model;
if (options.comparator !== void 0) this.comparator = options.comparator;
this._reset();
@@ -603,7 +606,7 @@
// Default options for `Collection#set`.
var setOptions = {add: true, remove: true, merge: true};
var addOptions = {add: true, remove: false};
var addOptions = {add: true, merge: false, remove: false};
// Define the Collection's inheritable methods.
_.extend(Collection.prototype, Events, {
@@ -629,17 +632,16 @@
// Add a model, or list of models to the set.
add: function(models, options) {
return this.set(models, _.extend({merge: false}, options, addOptions));
return this.set(models, _.defaults(options || {}, addOptions));
},
// Remove a model, or a list of models from the set.
remove: function(models, options) {
var singular = !_.isArray(models);
models = singular ? [models] : _.clone(models);
models = _.isArray(models) ? models.slice() : [models];
options || (options = {});
var i, l, index, model;
for (i = 0, l = models.length; i < l; i++) {
model = models[i] = this.get(models[i]);
model = this.get(models[i]);
if (!model) continue;
delete this._byId[model.id];
delete this._byId[model.cid];
@@ -652,7 +654,7 @@
}
this._removeReference(model);
}
return singular ? models[0] : models;
return this;
},
// Update a collection by `set`-ing a new list of models, adding new ones,
@@ -660,45 +662,31 @@
// 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) {
options = _.defaults({}, options, setOptions);
options = _.defaults(options || {}, setOptions);
if (options.parse) models = this.parse(models, options);
var singular = !_.isArray(models);
models = singular ? (models ? [models] : []) : _.clone(models);
var i, l, id, model, attrs, existing, sort;
if (!_.isArray(models)) models = models ? [models] : [];
var i, l, model, attrs, existing, sort;
var at = options.at;
var targetModel = this.model;
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;
// Turn bare objects into model references, and prevent invalid models
// from being added.
for (i = 0, l = models.length; i < l; i++) {
attrs = models[i];
if (attrs instanceof Model) {
id = model = attrs;
} else {
id = attrs[targetModel.prototype.idAttribute];
}
if (!(model = this._prepareModel(models[i], options))) continue;
// If a duplicate is found, prevent it from being added and
// optionally merge it into the existing model.
if (existing = this.get(id)) {
if (remove) modelMap[existing.cid] = true;
if (merge) {
attrs = attrs === model ? model.attributes : attrs;
if (options.parse) attrs = existing.parse(attrs, options);
existing.set(attrs, options);
if (existing = this.get(model)) {
if (options.remove) modelMap[existing.cid] = true;
if (options.merge) {
existing.set(model.attributes, options);
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(attrs, options);
if (!model) continue;
// This is a new model, push it to the `toAdd` list.
} else if (options.add) {
toAdd.push(model);
// Listen to added models' events, and index models for lookup by
@@ -707,11 +695,10 @@
this._byId[model.cid] = model;
if (model.id != null) this._byId[model.id] = model;
}
if (order) order.push(existing || model);
}
// Remove nonexistent models if appropriate.
if (remove) {
if (options.remove) {
for (i = 0, l = this.length; i < l; ++i) {
if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
}
@@ -719,35 +706,29 @@
}
// See if sorting is needed, update `length` and splice in new models.
if (toAdd.length || (order && order.length)) {
if (toAdd.length) {
if (sortable) sort = true;
this.length += toAdd.length;
if (at != null) {
for (i = 0, l = toAdd.length; i < l; i++) {
this.models.splice(at + i, 0, toAdd[i]);
}
splice.apply(this.models, [at, 0].concat(toAdd));
} else {
if (order) this.models.length = 0;
var orderedModels = order || toAdd;
for (i = 0, l = orderedModels.length; i < l; i++) {
this.models.push(orderedModels[i]);
}
push.apply(this.models, toAdd);
}
}
// Silently sort the collection if appropriate.
if (sort) this.sort({silent: true});
// Unless silenced, it's time to fire all appropriate add/sort events.
if (!options.silent) {
for (i = 0, l = toAdd.length; i < l; i++) {
(model = toAdd[i]).trigger('add', model, this, options);
}
if (sort || (order && order.length)) this.trigger('sort', this, options);
if (options.silent) return this;
// Trigger `add` events.
for (i = 0, l = toAdd.length; i < l; i++) {
(model = toAdd[i]).trigger('add', model, this, options);
}
// Return the added (or merged) model (or models).
return singular ? models[0] : models;
// Trigger `sort` if the collection was sorted.
if (sort) this.trigger('sort', this, options);
return this;
},
// When you have more items than you want to add or remove individually,
@@ -761,14 +742,16 @@
}
options.previousModels = this.models;
this._reset();
models = this.add(models, _.extend({silent: true}, options));
this.add(models, _.extend({silent: true}, options));
if (!options.silent) this.trigger('reset', this, options);
return models;
return this;
},
// Add a model to the end of the collection.
push: function(model, options) {
return this.add(model, _.extend({at: this.length}, options));
model = this._prepareModel(model, options);
this.add(model, _.extend({at: this.length}, options));
return model;
},
// Remove a model from the end of the collection.
@@ -780,7 +763,9 @@
// Add a model to the beginning of the collection.
unshift: function(model, options) {
return this.add(model, _.extend({at: 0}, options));
model = this._prepareModel(model, options);
this.add(model, _.extend({at: 0}, options));
return model;
},
// Remove a model from the beginning of the collection.
@@ -791,14 +776,14 @@
},
// Slice out a sub-array of models from the collection.
slice: function() {
return slice.apply(this.models, arguments);
slice: function(begin, end) {
return this.models.slice(begin, end);
},
// Get a model from the set by id.
get: function(obj) {
if (obj == null) return void 0;
return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj];
return this._byId[obj.id != null ? obj.id : obj.cid || obj];
},
// Get the model at the given index.
@@ -842,6 +827,16 @@
return this;
},
// Figure out the smallest index at which a model should be inserted so as
// to maintain order.
sortedIndex: function(model, value, context) {
value || (value = this.comparator);
var iterator = _.isFunction(value) ? value : function(model) {
return model.get(value);
};
return _.sortedIndex(this.models, model, iterator, context);
},
// Pluck an attribute from each model in the collection.
pluck: function(attr) {
return _.invoke(this.models, 'get', attr);
@@ -874,7 +869,7 @@
if (!options.wait) this.add(model, options);
var collection = this;
var success = options.success;
options.success = function(model, resp, options) {
options.success = function(resp) {
if (options.wait) collection.add(model, options);
if (success) success(model, resp, options);
};
@@ -908,12 +903,14 @@
if (!attrs.collection) attrs.collection = this;
return attrs;
}
options = options ? _.clone(options) : {};
options || (options = {});
options.collection = this;
var model = new this.model(attrs, options);
if (!model.validationError) return model;
this.trigger('invalid', this, model.validationError, options);
return false;
if (!model._validate(attrs, options)) {
this.trigger('invalid', this, attrs, options);
return false;
}
return model;
},
// Internal method to sever a model's ties to a collection.
@@ -945,8 +942,8 @@
'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
'lastIndexOf', 'isEmpty', 'chain'];
'tail', 'drop', 'last', 'without', 'indexOf', 'shuffle', 'lastIndexOf',
'isEmpty', 'chain'];
// Mix in each Underscore method as a proxy to `Collection#models`.
_.each(methods, function(method) {
@@ -985,8 +982,7 @@
// if an existing element is not provided...
var View = Backbone.View = function(options) {
this.cid = _.uniqueId('view');
options || (options = {});
_.extend(this, _.pick(options, viewOptions));
this._configure(options || {});
this._ensureElement();
this.initialize.apply(this, arguments);
this.delegateEvents();
@@ -1005,7 +1001,7 @@
tagName: 'div',
// jQuery delegate for element lookup, scoped to DOM elements within the
// current view. This should be preferred to global lookups where possible.
// current view. This should be prefered to global lookups where possible.
$: function(selector) {
return this.$el.find(selector);
},
@@ -1045,7 +1041,7 @@
//
// {
// 'mousedown .title': 'edit',
// 'click .button': 'save',
// 'click .button': 'save'
// 'click .open': function(e) { ... }
// }
//
@@ -1083,6 +1079,16 @@
return this;
},
// Performs the initial configuration of a View with a set of options.
// Keys with special meaning *(e.g. model, collection, id, className)* are
// attached directly to the view. See `viewOptions` for an exhaustive
// list.
_configure: function(options) {
if (this.options) options = _.extend({}, _.result(this, 'options'), options);
_.extend(this, _.pick(options, viewOptions));
this.options = options;
},
// Ensure that the View has a DOM element to render into.
// If `this.el` is a string, pass it through `$()`, take the first
// matching element, and re-assign it to `el`. Otherwise, create
@@ -1168,7 +1174,8 @@
// If we're sending a `PATCH` request, and we're in an old Internet Explorer
// that still has ActiveX enabled by default, override jQuery to use that
// for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
if (params.type === 'PATCH' && noXhrPatch) {
if (params.type === 'PATCH' && window.ActiveXObject &&
!(window.external && window.external.msActiveXFilteringEnabled)) {
params.xhr = function() {
return new ActiveXObject("Microsoft.XMLHTTP");
};
@@ -1180,8 +1187,6 @@
return xhr;
};
var noXhrPatch = typeof window !== 'undefined' && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
// Map from CRUD to HTTP for our default `Backbone.sync` implementation.
var methodMap = {
'create': 'POST',
@@ -1270,7 +1275,7 @@
_routeToRegExp: function(route) {
route = route.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, function(match, optional) {
.replace(namedParam, function(match, optional){
return optional ? match : '([^\/]+)';
})
.replace(splatParam, '(.*?)');
@@ -1320,9 +1325,6 @@
// Cached regex for removing a trailing slash.
var trailingSlash = /\/$/;
// Cached regex for stripping urls of hash and query.
var pathStripper = /[?#].*$/;
// Has the history handling already been started?
History.started = false;
@@ -1347,7 +1349,7 @@
if (this._hasPushState || !this._wantsHashChange || forcePushState) {
fragment = this.location.pathname;
var root = this.root.replace(trailingSlash, '');
if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
if (!fragment.indexOf(root)) fragment = fragment.substr(root.length);
} else {
fragment = this.getHash();
}
@@ -1363,7 +1365,7 @@
// Figure out the initial configuration. Do we need an iframe?
// Is pushState desired ... is it available?
this.options = _.extend({root: '/'}, this.options, options);
this.options = _.extend({}, {root: '/'}, this.options, options);
this.root = this.options.root;
this._wantsHashChange = this.options.hashChange !== false;
this._wantsPushState = !!this.options.pushState;
@@ -1396,25 +1398,19 @@
var loc = this.location;
var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
// Transition from hashChange to pushState or vice versa if both are
// requested.
if (this._wantsHashChange && this._wantsPushState) {
// 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 && !atRoot) {
this.fragment = this.getFragment(null, true);
this.location.replace(this.root + this.location.search + '#' + this.fragment);
// Return immediately as browser will do redirect to new url
return true;
// Or if we've started out with a hash-based route, but we're currently
// in a browser where it could be `pushState`-based instead...
} else if (this._hasPushState && atRoot && loc.hash) {
this.fragment = this.getHash().replace(routeStripper, '');
this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
}
// 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._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
this.fragment = this.getFragment(null, true);
this.location.replace(this.root + this.location.search + '#' + this.fragment);
// Return immediately as browser will do redirect to new url
return true;
// Or if we've started out with a hash-based route, but we're currently
// in a browser where it could be `pushState`-based instead...
} else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
this.fragment = this.getHash().replace(routeStripper, '');
this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
}
if (!this.options.silent) return this.loadUrl();
@@ -1443,20 +1439,21 @@
}
if (current === this.fragment) return false;
if (this.iframe) this.navigate(current);
this.loadUrl();
this.loadUrl() || this.loadUrl(this.getHash());
},
// Attempt to load the current URL fragment. If a route succeeds with a
// match, returns `true`. If no defined routes matches the fragment,
// returns `false`.
loadUrl: function(fragment) {
fragment = this.fragment = this.getFragment(fragment);
return _.any(this.handlers, function(handler) {
loadUrl: function(fragmentOverride) {
var fragment = this.fragment = this.getFragment(fragmentOverride);
var matched = _.any(this.handlers, function(handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
}
});
return matched;
},
// Save a fragment into the hash history, or replace the URL state if the
@@ -1468,18 +1465,11 @@
// you wish to modify the current URL without adding an entry to the history.
navigate: function(fragment, options) {
if (!History.started) return false;
if (!options || options === true) options = {trigger: !!options};
var url = this.root + (fragment = this.getFragment(fragment || ''));
// Strip the fragment of the query and hash for matching.
fragment = fragment.replace(pathStripper, '');
if (!options || options === true) options = {trigger: options};
fragment = this.getFragment(fragment || '');
if (this.fragment === fragment) return;
this.fragment = fragment;
// Don't include a trailing slash on the root.
if (fragment === '' && url !== '/') url = url.slice(0, -1);
var url = this.root + fragment;
// If pushState is available, we use it to set the fragment as a real URL.
if (this._hasPushState) {
@@ -1502,7 +1492,7 @@
} else {
return this.location.assign(url);
}
if (options.trigger) return this.loadUrl(fragment);
if (options.trigger) this.loadUrl(fragment);
},
// Update the hash location, either replacing the current entry, or adding
@@ -1570,7 +1560,7 @@
};
// Wrap an optional error callback with a fallback error event.
var wrapError = function(model, options) {
var wrapError = function (model, options) {
var error = options.error;
options.error = function(resp) {
if (error) error(model, resp, options);

View File

@@ -1,10 +1,12 @@
(function() {
$(document).ready(function() {
var a, b, c, d, e, col, otherCol;
module("Backbone.Collection", {
module("Backbone.Collection", _.extend(new Environment, {
setup: function() {
Environment.prototype.setup.apply(this, arguments);
a = new Backbone.Model({id: 3, label: 'a'});
b = new Backbone.Model({id: 2, label: 'b'});
c = new Backbone.Model({id: 1, label: 'c'});
@@ -14,7 +16,7 @@
otherCol = new Backbone.Collection();
}
});
}));
test("new and sort", 9, function() {
var counter = 0;
@@ -85,7 +87,7 @@
equal(col2.get(model.clone()), col2.first());
});
test("update index when id changes", 4, function() {
test("update index when id changes", 3, function() {
var col = new Backbone.Collection();
col.add([
{id : 0, name : 'one'},
@@ -93,10 +95,9 @@
]);
var one = col.get(0);
equal(one.get('name'), 'one');
col.on('change:name', function (model) { ok(this.get(model)); });
one.set({name: 'dalmatians', id : 101});
one.set({id : 101});
equal(col.get(0), null);
equal(col.get(101).get('name'), 'dalmatians');
equal(col.get(101).get('name'), 'one');
});
test("at", 1, function() {
@@ -225,13 +226,13 @@
});
test("add with parse and merge", function() {
var Model = Backbone.Model.extend({
parse: function (data) {
return data.model;
}
});
var collection = new Backbone.Collection();
collection.parse = function(attrs) {
return _.map(attrs, function(model) {
if (model.model) return model.model;
return model;
});
};
collection.model = Model;
collection.add({id: 1});
collection.add({model: {id: 1, name: 'Alf'}}, {parse: true, merge: true});
equal(collection.first().get('name'), 'Alf');
@@ -287,39 +288,6 @@
equal(otherRemoved, null);
});
test("add and remove return values", 13, function() {
var Even = Backbone.Model.extend({
validate: function(attrs) {
if (attrs.id % 2 !== 0) return "odd";
}
});
var col = new Backbone.Collection;
col.model = Even;
var list = col.add([{id: 2}, {id: 4}], {validate: true});
equal(list.length, 2);
ok(list[0] instanceof Backbone.Model);
equal(list[1], col.last());
equal(list[1].get('id'), 4);
list = col.add([{id: 3}, {id: 6}], {validate: true});
equal(col.length, 3);
equal(list[0], false);
equal(list[1].get('id'), 6);
var result = col.add({id: 6});
equal(result.cid, list[1].cid);
result = col.remove({id: 6});
equal(col.length, 2);
equal(result.id, 6);
list = col.remove([{id: 2}, {id: 8}]);
equal(col.length, 1);
equal(list[0].get('id'), 2);
equal(list[1], null);
});
test("shift and pop", 2, function() {
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
equal(col.shift().get('a'), 'a');
@@ -470,7 +438,7 @@
equal(model.collection, collection);
});
test("create with validate:true enforces validation", 3, function() {
test("create with validate:true enforces validation", 2, function() {
var ValidatingModel = Backbone.Model.extend({
validate: function(attrs) {
return "fail";
@@ -480,8 +448,7 @@
model: ValidatingModel
});
var col = new ValidatingCollection();
col.on('invalid', function (collection, error, options) {
equal(error, "fail");
col.on('invalid', function (collection, attrs, options) {
equal(options.validationError, 'fail');
});
equal(col.create({"foo":"bar"}, {validate:true}), false);
@@ -535,7 +502,7 @@
equal(coll.findWhere({a: 4}), void 0);
});
test("Underscore methods", 14, function() {
test("Underscore methods", 13, function() {
equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d');
equal(col.any(function(model){ return model.id === 100; }), false);
equal(col.any(function(model){ return model.id === 0; }), true);
@@ -553,7 +520,18 @@
.map(function(o){ return o.id * 2; })
.value(),
[4, 0]);
deepEqual(col.difference([c, d]), [a, b]);
});
test("sortedIndex", function () {
var model = new Backbone.Model({key: 2});
var collection = new (Backbone.Collection.extend({
comparator: 'key'
}))([model, {key: 1}]);
equal(collection.sortedIndex(model), 1);
equal(collection.sortedIndex(model, 'key'), 1);
equal(collection.sortedIndex(model, function (model) {
return model.get('key');
}), 1);
});
test("reset", 12, function() {
@@ -942,20 +920,6 @@
strictEqual(c.length, 0);
});
test("set with many models does not overflow the stack", function() {
var n = 150000;
var collection = new Backbone.Collection();
var models = [];
for (var i = 0; i < n; i++) {
models.push({id: i});
}
collection.set(models);
equal(collection.length, n);
collection.reset();
collection.set(models, {at: 0});
equal(collection.length, n);
});
test("set with only cids", 3, function() {
var m1 = new Backbone.Model;
var m2 = new Backbone.Model;
@@ -999,33 +963,17 @@
equal(col.first().get('key'), 'other');
col.set({id: 1, other: 'value'});
equal(col.first().get('key'), 'other');
equal(col.first().get('key'), 'value');
equal(col.length, 1);
});
test('merge without mutation', function () {
var Model = Backbone.Model.extend({
initialize: function (attrs, options) {
if (attrs.child) {
this.set('child', new Model(attrs.child, options), options);
}
}
});
var Collection = Backbone.Collection.extend({model: Model});
var data = [{id: 1, child: {id: 2}}];
var collection = new Collection(data);
equal(collection.first().id, 1);
collection.set(data);
equal(collection.first().id, 1);
collection.set([{id: 2, child: {id: 2}}].concat(data));
deepEqual(collection.pluck('id'), [2, 1]);
});
test("`set` and model level `parse`", function() {
var Model = Backbone.Model.extend({});
var Model = Backbone.Model.extend({
parse: function (res) { return res.model; }
});
var Collection = Backbone.Collection.extend({
model: Model,
parse: function (res) { return _.pluck(res.models, 'model'); }
parse: function (res) { return res.models; }
});
var model = new Model({id: 1});
var collection = new Collection(model);
@@ -1048,25 +996,6 @@
collection.set({}, {parse: true});
});
test('`set` matches input order in the absence of a comparator', function () {
var one = new Backbone.Model({id: 1});
var two = new Backbone.Model({id: 2});
var three = new Backbone.Model({id: 3});
var collection = new Backbone.Collection([one, two, three]);
collection.set([{id: 3}, {id: 2}, {id: 1}]);
deepEqual(collection.models, [three, two, one]);
collection.set([{id: 1}, {id: 2}]);
deepEqual(collection.models, [one, two]);
collection.set([two, three, one]);
deepEqual(collection.models, [two, three, one]);
collection.set([{id: 1}, {id: 2}], {remove: false});
deepEqual(collection.models, [two, three, one]);
collection.set([{id: 1}, {id: 2}, {id: 3}], {merge: false});
deepEqual(collection.models, [one, two, three]);
collection.set([three, two, one, {id: 4}], {add: false});
deepEqual(collection.models, [one, two, three]);
});
test("#1894 - Push should not trigger a sort", 0, function() {
var Collection = Backbone.Collection.extend({
comparator: 'id',
@@ -1077,13 +1006,6 @@
new Collection().push({id: 1});
});
test("#2428 - push duplicate models, return the correct one", 1, function() {
var col = new Backbone.Collection;
var model1 = col.push({id: 101});
var model2 = col.push({id: 101})
ok(model2.cid == model1.cid);
});
test("`set` with non-normal id", function() {
var Collection = Backbone.Collection.extend({
model: Backbone.Model.extend({idAttribute: '_id'})
@@ -1159,119 +1081,20 @@
collection.add(collection.models, {merge: true}); // don't sort
});
test("Attach options to collection.", 2, function() {
var model = new Backbone.Model;
var comparator = function(){};
test("Attach options to collection.", 3, function() {
var url = '/somewhere';
var model = new Backbone.Model;
var comparator = function(){};
var collection = new Backbone.Collection([], {
model: model,
comparator: comparator
});
var collection = new Backbone.Collection([], {
url: url,
model: model,
comparator: comparator
});
ok(collection.model === model);
ok(collection.comparator === comparator);
strictEqual(collection.url, url);
ok(collection.model === model);
ok(collection.comparator === comparator);
});
test("`add` overrides `set` flags", function () {
var collection = new Backbone.Collection();
collection.once('add', function (model, collection, options) {
collection.add({id: 2}, options);
});
collection.set({id: 1});
equal(collection.length, 2);
});
test("#2606 - Collection#create, success arguments", 1, function() {
var collection = new Backbone.Collection;
collection.url = 'test';
collection.create({}, {
success: function(model, resp, options) {
strictEqual(resp, 'response');
}
});
this.ajaxSettings.success('response');
});
test("#2612 - nested `parse` works with `Collection#set`", function() {
var Job = Backbone.Model.extend({
constructor: function() {
this.items = new Items();
Backbone.Model.apply(this, arguments);
},
parse: function(attrs) {
this.items.set(attrs.items, {parse: true});
return _.omit(attrs, 'items');
}
});
var Item = Backbone.Model.extend({
constructor: function() {
this.subItems = new Backbone.Collection();
Backbone.Model.apply(this, arguments);
},
parse: function(attrs) {
this.subItems.set(attrs.subItems, {parse: true});
return _.omit(attrs, 'subItems');
}
});
var Items = Backbone.Collection.extend({
model: Item
});
var data = {
name: 'JobName',
id: 1,
items: [{
id: 1,
name: 'Sub1',
subItems: [
{id: 1, subName: 'One'},
{id: 2, subName: 'Two'}
]
}, {
id: 2,
name: 'Sub2',
subItems: [
{id: 3, subName: 'Three'},
{id: 4, subName: 'Four'}
]
}]
};
var newData = {
name: 'NewJobName',
id: 1,
items: [{
id: 1,
name: 'NewSub1',
subItems: [
{id: 1,subName: 'NewOne'},
{id: 2,subName: 'NewTwo'}
]
}, {
id: 2,
name: 'NewSub2',
subItems: [
{id: 3,subName: 'NewThree'},
{id: 4,subName: 'NewFour'}
]
}]
};
var job = new Job(data, {parse: true});
equal(job.get('name'), 'JobName');
equal(job.items.at(0).get('name'), 'Sub1');
equal(job.items.length, 2);
equal(job.items.get(1).subItems.get(1).get('subName'), 'One');
equal(job.items.get(2).subItems.get(3).get('subName'), 'Three');
job.set(job.parse(newData, {parse: true}));
equal(job.get('name'), 'NewJobName');
equal(job.items.at(0).get('name'), 'NewSub1');
equal(job.items.length, 2);
equal(job.items.get(1).subItems.get(1).get('subName'), 'NewOne');
equal(job.items.get(2).subItems.get(3).get('subName'), 'NewThree');
});
})();
});

View File

@@ -1,35 +1,45 @@
(function() {
var sync = Backbone.sync;
var ajax = Backbone.ajax;
var emulateHTTP = Backbone.emulateHTTP;
var emulateJSON = Backbone.emulateJSON;
var Environment = this.Environment = function(){};
QUnit.testStart(function() {
var env = this.config.current.testEnvironment;
_.extend(Environment.prototype, {
// Capture ajax settings for comparison.
Backbone.ajax = function(settings) {
env.ajaxSettings = settings;
};
ajax: Backbone.ajax,
// Capture the arguments to Backbone.sync for comparison.
Backbone.sync = function(method, model, options) {
env.syncArgs = {
method: method,
model: model,
options: options
sync: Backbone.sync,
emulateHTTP: Backbone.emulateHTTP,
emulateJSON: Backbone.emulateJSON,
setup: function() {
var env = this;
// Capture ajax settings for comparison.
Backbone.ajax = function(settings) {
env.ajaxSettings = settings;
};
sync.apply(this, arguments);
};
});
// Capture the arguments to Backbone.sync for comparison.
Backbone.sync = function(method, model, options) {
env.syncArgs = {
method: method,
model: model,
options: options
};
env.sync.apply(this, arguments);
};
},
teardown: function() {
this.syncArgs = null;
this.ajaxSettings = null;
Backbone.sync = this.sync;
Backbone.ajax = this.ajax;
Backbone.emulateHTTP = this.emulateHTTP;
Backbone.emulateJSON = this.emulateJSON;
}
QUnit.testDone(function() {
Backbone.sync = sync;
Backbone.ajax = ajax;
Backbone.emulateHTTP = emulateHTTP;
Backbone.emulateJSON = emulateJSON;
});
})();

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
module("Backbone.Events");
@@ -152,31 +152,6 @@
e.trigger("foo");
});
test("stopListening cleans up references", 4, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var fn = function() {};
a.listenTo(b, 'all', fn).stopListening();
equal(_.size(a._listeningTo), 0);
a.listenTo(b, 'all', fn).stopListening(b);
equal(_.size(a._listeningTo), 0);
a.listenTo(b, 'all', fn).stopListening(null, 'all');
equal(_.size(a._listeningTo), 0);
a.listenTo(b, 'all', fn).stopListening(null, null, fn);
equal(_.size(a._listeningTo), 0);
});
test("listenTo and stopListening cleaning up references", 2, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, 'all', function(){ ok(true); });
b.trigger('anything');
a.listenTo(b, 'other', function(){ ok(false); });
a.stopListening(b, 'other');
a.stopListening(b, 'all');
equal(_.keys(a._listeningTo).length, 0);
});
test("listenTo with empty callback doesn't throw an error", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, "foo", null);
@@ -474,4 +449,4 @@
equal(obj, obj.stopListening());
});
})();
});

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
var proxy = Backbone.Model.extend();
var klass = Backbone.Collection.extend({
@@ -6,9 +6,10 @@
});
var doc, collection;
module("Backbone.Model", {
module("Backbone.Model", _.extend(new Environment, {
setup: function() {
Environment.prototype.setup.apply(this, arguments);
doc = new proxy({
id : '1-the-tempest',
title : "The Tempest",
@@ -19,7 +20,7 @@
collection.add(doc);
}
});
}));
test("initialize", 3, function() {
var Model = Backbone.Model.extend({
@@ -110,6 +111,13 @@
equal(model.url(), '/nested/1/collection/2');
});
test('url and urlRoot are directly attached if passed in the options', 2, function () {
var model = new Backbone.Model({a: 1}, {url: '/test'});
var model2 = new Backbone.Model({a: 2}, {urlRoot: '/test2'});
equal(model.url, '/test');
equal(model2.urlRoot, '/test2');
});
test("underscore methods", 5, function() {
var model = new Backbone.Model({ 'foo': 'a', 'bar': 'b', 'baz': 'c' });
var model2 = model.clone();
@@ -704,22 +712,6 @@
ok(this.syncArgs.model === model);
});
test("save without `wait` doesn't set invalid attributes", function () {
var model = new Backbone.Model();
model.validate = function () { return 1; }
model.save({a: 1});
equal(model.get('a'), void 0);
});
test("save doesn't validate twice", function () {
var model = new Backbone.Model();
var times = 0;
model.sync = function () {};
model.validate = function () { ++times; }
model.save({});
equal(times, 1);
});
test("`hasChanged` for falsey keys", 2, function() {
var model = new Backbone.Model();
model.set({x: true}, {silent: true});
@@ -1107,4 +1099,4 @@
model.set({a: true});
});
})();
});

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
module("Backbone.noConflict");
@@ -9,4 +9,4 @@
equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
});
})();
});

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
var router = null;
var location = null;
@@ -75,8 +75,6 @@
"counter": "counter",
"search/:query": "search",
"search/:query/p:page": "search",
"charñ": "charUTF",
"char%C3%B1": "charEscaped",
"contacts": "contacts",
"contacts/new": "newContact",
"contacts/:id": "loadContact",
@@ -105,19 +103,11 @@
this.count++;
},
search: function(query, page) {
search : function(query, page) {
this.query = query;
this.page = page;
},
charUTF: function() {
this.charType = 'UTF';
},
charEscaped: function() {
this.charType = 'escaped';
},
contacts: function(){
this.contact = 'index';
},
@@ -214,10 +204,6 @@
equal(router.page, '20');
});
test("reports matched route via nagivate", 1, function() {
ok(Backbone.history.navigate('search/manhattan/p20', true));
});
test("route precedence via navigate", 6, function(){
// check both 0.9.x and backwards-compatibility options
_.each([ { trigger: true }, true ], function( options ){
@@ -363,13 +349,6 @@
equal(lastRoute, 'search');
});
test("#2666 - Hashes with UTF8 in them.", 2, function() {
Backbone.history.navigate('charñ', {trigger: true});
equal(router.charType, 'UTF');
Backbone.history.navigate('char%C3%B1', {trigger: true});
equal(router.charType, 'escaped');
});
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
Backbone.history.stop();
location.replace('http://example.com/path/name#hash');
@@ -630,100 +609,4 @@
deepEqual({home: "root", index: "index.html", show: "show", search: "search"}, router.routes);
});
test("#2538 - hashChange to pushState only if both requested.", 0, function() {
Backbone.history.stop();
location.replace('http://example.com/root?a=b#x/y');
Backbone.history = _.extend(new Backbone.History, {
location: location,
history: {
pushState: function(){},
replaceState: function(){ ok(false); }
}
});
Backbone.history.start({
root: 'root',
pushState: true,
hashChange: false
});
});
test('No hash fallback.', 0, function() {
Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {
location: location,
history: {
pushState: function(){},
replaceState: function(){}
}
});
var Router = Backbone.Router.extend({
routes: {
hash: function() { ok(false); }
}
});
var router = new Router;
location.replace('http://example.com/');
Backbone.history.start({
pushState: true,
hashChange: false
});
location.replace('http://example.com/nomatch#hash');
Backbone.history.checkUrl();
});
test('#2656 - No trailing slash on root.', 1, function() {
Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {
location: location,
history: {
pushState: function(state, title, url){
strictEqual(url, '/root');
}
}
});
location.replace('http://example.com/root/path');
Backbone.history.start({pushState: true, root: 'root'});
Backbone.history.navigate('');
});
test('#2656 - No trailing slash on root.', 1, function() {
Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {
location: location,
history: {
pushState: function(state, title, url) {
strictEqual(url, '/');
}
}
});
location.replace('http://example.com/path');
Backbone.history.start({pushState: true});
Backbone.history.navigate('');
});
test('#2765 - Fragment matching sans query/hash.', 2, function() {
Backbone.history.stop();
Backbone.history = _.extend(new Backbone.History, {
location: location,
history: {
pushState: function(state, title, url) {
strictEqual(url, '/path?query#hash');
}
}
});
var Router = Backbone.Router.extend({
routes: {
path: function() { ok(true); }
}
});
var router = new Router;
location.replace('http://example.com/');
Backbone.history.start({pushState: true});
Backbone.history.navigate('path?query#hash', true);
});
})();
});

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
var Library = Backbone.Collection.extend({
url : function() { return '/library'; }
@@ -11,18 +11,20 @@
length : 123
};
module("Backbone.sync", {
module("Backbone.sync", _.extend(new Environment, {
setup : function() {
Environment.prototype.setup.apply(this, arguments);
library = new Library;
library.create(attrs, {wait: false});
},
teardown: function() {
Environment.prototype.teardown.apply(this, arguments);
Backbone.emulateHTTP = false;
}
});
}));
test("read", 4, function() {
library.fetch();
@@ -207,4 +209,4 @@
strictEqual(this.ajaxSettings.beforeSend(xhr), false);
});
})();
});

View File

@@ -1,4 +1,4 @@
(function() {
$(document).ready(function() {
var view;
@@ -14,10 +14,13 @@
});
test("constructor", 3, function() {
test("constructor", 6, function() {
equal(view.el.id, 'test-view');
equal(view.el.className, 'test-view');
equal(view.el.other, void 0);
equal(view.options.id, 'test-view');
equal(view.options.className, 'test-view');
equal(view.options.other, 'non-special-option');
});
test("jQuery", 1, function() {
@@ -153,6 +156,30 @@
strictEqual(new View().el.id, 'id');
});
test("with options function", 3, function() {
var View1 = Backbone.View.extend({
options: function() {
return {
title: 'title1',
acceptText: 'confirm'
};
}
});
var View2 = View1.extend({
options: function() {
return _.extend(View1.prototype.options.call(this), {
title: 'title2',
fixed: true
});
}
});
strictEqual(new View2().options.title, 'title2');
strictEqual(new View2().options.acceptText, 'confirm');
strictEqual(new View2().options.fixed, true);
});
test("with attributes", 2, function() {
var View = Backbone.View.extend({
attributes: {
@@ -292,7 +319,7 @@
view.collection.trigger('x');
});
test("Provide function for el.", 2, function() {
test("Provide function for el.", 1, function() {
var View = Backbone.View.extend({
el: function() {
return "<p><a></a></p>";
@@ -300,8 +327,7 @@
});
var view = new View;
ok(view.$el.is('p'));
ok(view.$el.has('a'));
ok(view.$el.is('p:has(a)'));
});
test("events passed in options", 2, function() {
@@ -328,4 +354,4 @@
equal(counter, 4);
});
})();
});

128
vendor/benchmark.js/README.md vendored Normal file
View File

@@ -0,0 +1,128 @@
# Benchmark.js <sup>v1.0.0</sup>
[![build status](https://secure.travis-ci.org/bestiejs/benchmark.js.png)](http://travis-ci.org/bestiejs/benchmark.js)
A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
## Download
* [Development source](https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js)
## Dive in
Weve got [API docs](http://benchmarkjs.com/docs) and [unit tests](http://benchmarkjs.com/tests).
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
## Support
Benchmark.js has been tested in at least Chrome 5~27, Firefox 2~21, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.10.7, Narwhal 0.3.2, PhantomJS 1.9.0, RingoJS 0.9, and Rhino 1.7RC5.
## Installation and usage
Benchmark.js only hard dependency is [Lo-Dash](http://lodash.com/).
In a browser:
```html
<script src="lodash.js"></script>
<script src="benchmark.js"></script>
```
Optionally, expose Javas nanosecond timer by adding the `nano` applet to the `<body>`:
```html
<applet code="nano" archive="nano.jar"></applet>
```
Or enable Chromes microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
--enable-benchmarking
Via [npm](http://npmjs.org/):
```bash
npm install benchmark
```
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
```js
var Benchmark = require('benchmark');
```
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
```bash
npm install microtime
```
In [RingoJS v0.7.0-](http://ringojs.org/):
```js
var Benchmark = require('benchmark').Benchmark;
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('benchmark.js');
```
In an AMD loader like [RequireJS](http://requirejs.org/):
```js
require({
'paths': {
'benchmark': 'path/to/benchmark',
'lodash': 'path/to/lodash',
'platform': 'path/to/platform'
}
},
['benchmark'], function(Benchmark) {
console.log(Benchmark.platform.name);
});
```
Usage example:
```js
var suite = new Benchmark.Suite;
// add tests
suite.add('RegExp#test', function() {
/o/.test('Hello World!');
})
.add('String#indexOf', function() {
'Hello World!'.indexOf('o') > -1;
})
// add listeners
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
// run async
.run({ 'async': true });
// logs:
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
// > Fastest is String#indexOf
```
## BestieJS
Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Authors
| [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") | [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
|---|---|
| [Mathias Bynens](http://mathiasbynens.be/) | [John-David Dalton](http://allyoucanleet.com/) |
## Contributors
| [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") |
|---|
| [Kit Cambridge](http://kitcambridge.github.io/) |

View File

@@ -5,7 +5,7 @@
* Modified by John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit>
*/
;(function(root, undefined) {
;(function(window, undefined) {
'use strict';
/** Detect free variable `define` */
@@ -21,10 +21,10 @@
/** Detect free variable `require` */
var freeRequire = typeof require == 'function' && require;
/** Detect free variable `global`, from Node.js or Browserified code, and use it as `root` */
/** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
window = freeGlobal;
}
/** Used to assign each benchmark an incrimented id */
@@ -105,12 +105,12 @@
*
* @static
* @memberOf Benchmark
* @param {Object} [context=root] The context object.
* @param {Object} [context=window] The context object.
* @returns {Function} Returns the `Benchmark` function.
*/
function runInContext(context) {
// exit early if unable to acquire lodash
var _ = context && context._ || req('lodash') || root._;
var _ = context && context._ || req('lodash') || window._;
if (!_) {
Benchmark.runInContext = runInContext;
return Benchmark;
@@ -118,8 +118,8 @@
// Avoid issues with some ES3 environments that attempt to use values, named
// after built-in constructors like `Object`, for the creation of literals.
// ES5 clears this up by stating that literals must use built-in constructors.
// See http://es5.github.io/#x11.1.5.
context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
// See http://es5.github.com/#x11.1.5.
context = context ? _.defaults(window.Object(), context, _.pick(window, contextProps)) : window;
/** Native constructor references */
var Array = context.Array,
@@ -131,8 +131,8 @@
String = context.String;
/** Used for `Array` and `Object` method references */
var arrayRef = [],
objectProto = Object.prototype;
var arrayRef = Array(),
objectRef = Object();
/** Native method shortcuts */
var abs = Math.abs,
@@ -147,7 +147,7 @@
shift = arrayRef.shift,
slice = arrayRef.slice,
sqrt = Math.sqrt,
toString = objectProto.toString;
toString = objectRef.toString;
/** Detect DOM document object */
var doc = isHostType(context, 'document') && context.document;
@@ -191,7 +191,7 @@
* Detect Adobe AIR.
*
* @memberOf Benchmark.support
* @type boolean
* @type Boolean
*/
support.air = isClassOf(context.runtime, 'ScriptBridgingProxyObject');
@@ -199,7 +199,7 @@
* Detect if in a browser environment.
*
* @memberOf Benchmark.support
* @type boolean
* @type Boolean
*/
support.browser = doc && isHostType(context, 'navigator') && !isHostType(context, 'phantom');
@@ -207,7 +207,7 @@
* Detect if Java is enabled/exposed.
*
* @memberOf Benchmark.support
* @type boolean
* @type Boolean
*/
support.java = isClassOf(context.java, 'JavaPackage');
@@ -215,7 +215,7 @@
* Detect if the Timers API exists.
*
* @memberOf Benchmark.support
* @type boolean
* @type Boolean
*/
support.timeout = isHostType(context, 'setTimeout') && isHostType(context, 'clearTimeout');
@@ -224,7 +224,7 @@
*
* @name decompilation
* @memberOf Benchmark.support
* @type boolean
* @type Boolean
*/
try {
// Safari 2.x removes commas in object literals
@@ -254,7 +254,7 @@
*
* @private
* @memberOf timer
* @type {Function|Object}
* @type Function|Object
*/
'ns': Date,
@@ -283,8 +283,8 @@
* The Benchmark constructor.
*
* @constructor
* @param {string} name A name to identify the benchmark.
* @param {Function|string} fn The test to benchmark.
* @param {String} name A name to identify the benchmark.
* @param {Function|String} fn The test to benchmark.
* @param {Object} [options={}] Options object.
* @example
*
@@ -410,7 +410,7 @@
*
* @constructor
* @memberOf Benchmark
* @param {Object|string} type The event type.
* @param {String|Object} type The event type.
*/
function Event(type) {
var event = this;
@@ -427,7 +427,7 @@
*
* @constructor
* @memberOf Benchmark
* @param {string} name A name to identify the suite.
* @param {String} name A name to identify the suite.
* @param {Object} [options={}] Options object.
* @example
*
@@ -483,8 +483,8 @@
* A deep clone utility.
*
* @private
* @param {*} value The value to clone.
* @returns {*} The cloned value.
* @param {Mixed} value The value to clone.
* @returns {Mixed} The cloned value.
*/
var cloneDeep = _.partialRight(_.cloneDeep, function(value) {
// do not clone non-Object objects
@@ -497,8 +497,8 @@
* Creates a function from the given arguments string and body.
*
* @private
* @param {string} args The comma separated function arguments.
* @param {string} body The function body.
* @param {String} args The comma separated function arguments.
* @param {String} body The function body.
* @returns {Function} The new function.
*/
function createFunction() {
@@ -546,19 +546,33 @@
*
* @private
* @param {Function} fn The function.
* @returns {string} The argument name.
* @returns {String} The argument name.
*/
function getFirstArgument(fn) {
return (!_.has(fn, 'toString') &&
(/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
}
/**
* Computes the geometric mean (log-average) of a sample.
* See http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms.
*
* @private
* @param {Array} sample The sample.
* @returns {Number} The geometric mean.
*/
function getGeometricMean(sample) {
return pow(Math.E, _.reduce(sample, function(sum, x) {
return sum + log(x);
}) / sample.length) || 0;
}
/**
* Computes the arithmetic mean of a sample.
*
* @private
* @param {Array} sample The sample.
* @returns {number} The mean.
* @returns {Number} The mean.
*/
function getMean(sample) {
return (_.reduce(sample, function(sum, x) {
@@ -571,8 +585,8 @@
*
* @private
* @param {Function} fn The function.
* @param {string} altSource A string used when a function's source code is unretrievable.
* @returns {string} The function's source code.
* @param {String} altSource A string used when a function's source code is unretrievable.
* @returns {String} The function's source code.
*/
function getSource(fn, altSource) {
var result = altSource;
@@ -595,9 +609,9 @@
* Checks if an object is of the specified class.
*
* @private
* @param {*} value The value to check.
* @param {string} name The name of the class.
* @returns {boolean} Returns `true` if the value is of the specified class, else `false`.
* @param {Mixed} value The value to check.
* @param {String} name The name of the class.
* @returns {Boolean} Returns `true` if the value is of the specified class, else `false`.
*/
function isClassOf(value, name) {
return value != null && toString.call(value) == '[object ' + name + ']';
@@ -609,9 +623,9 @@
* types of "object", "function", or "unknown".
*
* @private
* @param {*} object The owner of the property.
* @param {string} property The property to check.
* @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
* @param {Mixed} object The owner of the property.
* @param {String} property The property to check.
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
*/
function isHostType(object, property) {
if (object == null) {
@@ -625,8 +639,8 @@
* Checks if a value can be safely coerced to a string.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the value can be coerced, else `false`.
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if the value can be coerced, else `false`.
*/
function isStringable(value) {
return _.has(value, 'toString') || isClassOf(value, 'String');
@@ -645,8 +659,8 @@
* A wrapper around require() to suppress `module missing` errors.
*
* @private
* @param {string} id The module id.
* @returns {*} The exported module or `null`.
* @param {String} id The module id.
* @returns {Mixed} The exported module or `null`.
*/
function req(id) {
try {
@@ -659,7 +673,7 @@
* Runs a snippet of JavaScript via script injection.
*
* @private
* @param {string} code The code to run.
* @param {String} code The code to run.
*/
function runScript(code) {
var anchor = freeDefine ? define.amd : Benchmark,
@@ -690,20 +704,20 @@
* A helper function for setting options/event handlers.
*
* @private
* @param {Object} object The benchmark or suite instance.
* @param {Object} bench The benchmark instance.
* @param {Object} [options={}] Options object.
*/
function setOptions(object, options) {
options = _.extend({}, object.constructor.options, options);
object.options = _.forOwn(options, function(value, key) {
function setOptions(bench, options) {
options = _.extend({}, bench.constructor.options, options);
bench.options = _.forOwn(options, function(value, key) {
if (value != null) {
// add event listeners
if (/^on[A-Z]/.test(key)) {
_.each(key.split(' '), function(key) {
object.on(key.slice(2).toLowerCase(), value);
bench.on(key.slice(2).toLowerCase(), value);
});
} else if (!_.has(object, key)) {
object[key] = cloneDeep(value);
} else if (!_.has(bench, key)) {
bench[key] = cloneDeep(value);
}
}
});
@@ -745,8 +759,8 @@
* @static
* @memberOf Benchmark
* @param {Array} array The array to iterate over.
* @param {Function|string} callback The function/alias called per iteration.
* @param {*} thisArg The `this` binding for the callback.
* @param {Function|String} callback The function/alias called per iteration.
* @param {Mixed} thisArg The `this` binding for the callback.
* @returns {Array} A new array of values that passed callback filter.
* @example
*
@@ -790,8 +804,8 @@
*
* @static
* @memberOf Benchmark
* @param {number} number The number to convert.
* @returns {string} The more readable string representation.
* @param {Number} number The number to convert.
* @returns {String} The more readable string representation.
*/
function formatNumber(number) {
number = String(number).split('.');
@@ -805,8 +819,8 @@
* @static
* @memberOf Benchmark
* @param {Array} benches Array of benchmarks to iterate over.
* @param {Object|string} name The name of the method to invoke OR options object.
* @param {...*} [arg] Arguments to invoke the method with.
* @param {String|Object} name The name of the method to invoke OR options object.
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
* @returns {Array} A new array of values returned from each method invoked.
* @example
*
@@ -986,9 +1000,9 @@
* @static
* @memberOf Benchmark
* @param {Array|Object} object The object to operate on.
* @param {string} [separator1=','] The separator used between key-value pairs.
* @param {string} [separator2=': '] The separator used between keys and values.
* @returns {string} The joined result.
* @param {String} [separator1=','] The separator used between key-value pairs.
* @param {String} [separator2=': '] The separator used between keys and values.
* @returns {String} The joined result.
*/
function join(object, separator1, separator2) {
var result = [],
@@ -1038,8 +1052,8 @@
* Adds a test to the benchmark suite.
*
* @memberOf Benchmark.Suite
* @param {string} name A name to identify the benchmark.
* @param {Function|string} fn The test to benchmark.
* @param {String} name A name to identify the benchmark.
* @param {Function|String} fn The test to benchmark.
* @param {Object} [options={}] Options object.
* @returns {Object} The benchmark instance.
* @example
@@ -1110,7 +1124,7 @@
*
* @name filter
* @memberOf Benchmark.Suite
* @param {Function|string} callback The function/alias called per iteration.
* @param {Function|String} callback The function/alias called per iteration.
* @returns {Object} A new suite of benchmarks that passed callback filter.
*/
function filterSuite(callback) {
@@ -1142,7 +1156,7 @@
// reset if the state has changed
else if ((suite.aborted || suite.running) &&
(suite.emit(event = Event('reset')), !event.cancelled)) {
suite.aborted = suite.running = false;
suite.running = false;
if (!aborting) {
invoke(suite, 'reset');
}
@@ -1201,8 +1215,8 @@
* Executes all registered listeners of the specified event type.
*
* @memberOf Benchmark, Benchmark.Suite
* @param {Object|string} type The event type or object.
* @returns {*} Returns the return value of the last listener executed.
* @param {String|Object} type The event type or object.
* @returns {Mixed} Returns the return value of the last listener executed.
*/
function emit(type) {
var listeners,
@@ -1231,7 +1245,7 @@
* to add or remove listeners.
*
* @memberOf Benchmark, Benchmark.Suite
* @param {string} type The event type.
* @param {String} type The event type.
* @returns {Array} The listeners array.
*/
function listeners(type) {
@@ -1247,7 +1261,7 @@
* or unregisters all listeners for all event types.
*
* @memberOf Benchmark, Benchmark.Suite
* @param {string} [type] The event type.
* @param {String} [type] The event type.
* @param {Function} [listener] The function to unregister.
* @returns {Object} The benchmark instance.
* @example
@@ -1298,7 +1312,7 @@
* Registers a listener for the specified event type(s).
*
* @memberOf Benchmark, Benchmark.Suite
* @param {string} type The event type.
* @param {String} type The event type.
* @param {Function} listener The function to register.
* @returns {Object} The benchmark instance.
* @example
@@ -1392,7 +1406,7 @@
*
* @memberOf Benchmark
* @param {Object} other The benchmark to compare.
* @returns {number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.
* @returns {Number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.
*/
function compare(other) {
var critical,
@@ -1516,7 +1530,7 @@
*
* @name toString
* @memberOf Benchmark
* @returns {string} A string representation of the benchmark instance.
* @returns {String} A string representation of the benchmark instance.
*/
function toStringBench() {
var bench = this,
@@ -1544,7 +1558,7 @@
*
* @private
* @param {Object} bench The benchmark instance.
* @returns {number} The time taken.
* @returns {Number} The time taken.
*/
function clock() {
var applet,
@@ -1555,119 +1569,16 @@
// lazy define for hi-res timers
clock = function(clone) {
var deferred;
templateData.uid = uid + uidCounter++;
if (clone instanceof Deferred) {
deferred = clone;
clone = deferred.benchmark;
}
var bench = clone._original,
stringable = isStringable(bench.fn),
count = bench.count = clone.count,
decompilable = support.decompilation || stringable,
id = bench.id,
name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),
result = 0;
// init `minTime` if needed
clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);
// repair nanosecond timer
// (some Chrome builds erase the `ns` variable after millions of executions)
if (applet) {
try {
timer.ns.nanoTime();
} catch(e) {
// use non-element to avoid issues with libs that augment them
timer.ns = new applet.Packages.nano;
}
}
// Compile in setup/teardown functions and the test loop.
// Create a new compiled test, instead of using the cached `bench.compiled`,
// to avoid potential engine optimizations enabled over the life of the test.
var funcBody = deferred
? 'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;' +
// when `deferred.cycles` is `0` then...
'if(!d#.cycles){' +
// set `deferred.fn`
'd#.fn=function(){var ${fnArg}=d#;if(typeof f#=="function"){try{${fn}\n}catch(e#){f#(d#)}}else{${fn}\n}};' +
// set `deferred.teardown`
'd#.teardown=function(){d#.cycles=0;if(typeof td#=="function"){try{${teardown}\n}catch(e#){td#()}}else{${teardown}\n}};' +
// execute the benchmark's `setup`
'if(typeof su#=="function"){try{${setup}\n}catch(e#){su#()}}else{${setup}\n};' +
// start timer
't#.start(d#);' +
// execute `deferred.fn` and return a dummy object
'}d#.fn();return{uid:"${uid}"}'
: 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\n${begin};' +
'while(i#--){${fn}\n}${end};${teardown}\nreturn{elapsed:r#,uid:"${uid}"}';
var compiled = bench.compiled = clone.compiled = createCompiled(bench, deferred, funcBody),
isEmpty = !(templateData.fn || stringable);
try {
if (isEmpty) {
// Firefox may remove dead code from Function#toString results
// http://bugzil.la/536085
throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
}
else if (!deferred) {
// pretest to determine if compiled code is exits early, usually by a
// rogue `return` statement, by checking for a return object with the uid
bench.count = 1;
compiled = (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled;
bench.count = count;
}
} catch(e) {
compiled = null;
clone.error = e || new Error(String(e));
bench.count = count;
}
// fallback when a test exits early or errors during pretest
if (decompilable && !compiled && !deferred && !isEmpty) {
funcBody = (
clone.error && !stringable
? 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count'
: 'function f#(){${fn}\n}var r#,s#,m#=this,i#=m#.count'
) +
',n#=t#.ns;${setup}\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};' +
'delete m#.f#;${teardown}\nreturn{elapsed:r#}';
compiled = createCompiled(bench, deferred, funcBody);
try {
// pretest one more time to check for errors
bench.count = 1;
compiled.call(bench, context, timer);
bench.count = count;
delete clone.error;
}
catch(e) {
bench.count = count;
if (!clone.error) {
clone.error = e || new Error(String(e));
}
}
}
// if no errors run the full test loop
if (!clone.error) {
compiled = bench.compiled = clone.compiled = createCompiled(bench, deferred, funcBody);
result = compiled.call(deferred || bench, context, timer).elapsed;
}
return result;
};
/*----------------------------------------------------------------------*/
/**
* Creates a compiled function from the given function `body`.
*/
function createCompiled(bench, deferred, body) {
var fn = bench.fn,
fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '';
templateData.uid = uid + uidCounter++;
fn = bench.fn,
fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '',
stringable = isStringable(fn);
_.extend(templateData, {
'setup': getSource(bench.setup, interpolate('m#.setup()')),
@@ -1714,6 +1625,28 @@
'end': interpolate('r#=(new n#-s#)/1e3')
});
}
var count = bench.count = clone.count,
decompilable = support.decompilation || stringable,
id = bench.id,
isEmpty = !(templateData.fn || stringable),
name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),
ns = timer.ns,
result = 0;
// init `minTime` if needed
clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);
// repair nanosecond timer
// (some Chrome builds erase the `ns` variable after millions of executions)
if (applet) {
try {
ns.nanoTime();
} catch(e) {
// use non-element to avoid issues with libs that augment them
ns = timer.ns = new applet.Packages.nano;
}
}
// define `timer` methods
timer.start = createFunction(
interpolate('o#'),
@@ -1725,7 +1658,92 @@
interpolate('var n#=this.ns,s#=o#.timeStamp,${end};o#.elapsed=r#')
);
// create compiled test
// Compile in setup/teardown functions and the test loop.
// Create a new compiled test, instead of using the cached `bench.compiled`,
// to avoid potential engine optimizations enabled over the life of the test.
var compiled = bench.compiled = createCompiled(
deferred
? 'var d#=this,${fnArg}=d#,m#=d#.benchmark._original,f#=m#.fn,su#=m#.setup,td#=m#.teardown;' +
// when `deferred.cycles` is `0` then...
'if(!d#.cycles){' +
// set `deferred.fn`
'd#.fn=function(){var ${fnArg}=d#;if(typeof f#=="function"){try{${fn}\n}catch(e#){f#(d#)}}else{${fn}\n}};' +
// set `deferred.teardown`
'd#.teardown=function(){d#.cycles=0;if(typeof td#=="function"){try{${teardown}\n}catch(e#){td#()}}else{${teardown}\n}};' +
// execute the benchmark's `setup`
'if(typeof su#=="function"){try{${setup}\n}catch(e#){su#()}}else{${setup}\n};' +
// start timer
't#.start(d#);' +
// execute `deferred.fn` and return a dummy object
'}d#.fn();return{uid:"${uid}"}'
: 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count,n#=t#.ns;${setup}\n${begin};' +
'while(i#--){${fn}\n}${end};${teardown}\nreturn{elapsed:r#,uid:"${uid}"}'
);
try {
if (isEmpty) {
// Firefox may remove dead code from Function#toString results
// http://bugzil.la/536085
throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
}
else if (!deferred) {
// pretest to determine if compiled code is exits early, usually by a
// rogue `return` statement, by checking for a return object with the uid
bench.count = 1;
compiled = (compiled.call(bench, context, timer) || {}).uid == templateData.uid && compiled;
bench.count = count;
}
} catch(e) {
compiled = null;
clone.error = e || new Error(String(e));
bench.count = count;
}
// fallback when a test exits early or errors during pretest
if (decompilable && !compiled && !deferred && !isEmpty) {
compiled = createCompiled(
(clone.error && !stringable
? 'var r#,s#,m#=this,f#=m#.fn,i#=m#.count'
: 'function f#(){${fn}\n}var r#,s#,m#=this,i#=m#.count'
) +
',n#=t#.ns;${setup}\n${begin};m#.f#=f#;while(i#--){m#.f#()}${end};' +
'delete m#.f#;${teardown}\nreturn{elapsed:r#}'
);
try {
// pretest one more time to check for errors
bench.count = 1;
compiled.call(bench, context, timer);
bench.compiled = compiled;
bench.count = count;
delete clone.error;
}
catch(e) {
bench.count = count;
if (clone.error) {
compiled = null;
} else {
bench.compiled = compiled;
clone.error = e || new Error(String(e));
}
}
}
// assign `compiled` to `clone` before calling in case a deferred benchmark
// immediately calls `deferred.resolve()`
clone.compiled = compiled;
// if no errors run the full test loop
if (!clone.error) {
result = compiled.call(deferred || bench, context, timer).elapsed;
}
return result;
};
/*----------------------------------------------------------------------*/
/**
* Creates a compiled function from the given function `body`.
*/
function createCompiled(body) {
return createFunction(
interpolate('window,t#'),
'var global = window, clearTimeout = global.clearTimeout, setTimeout = global.setTimeout;\n' +
@@ -2182,7 +2200,7 @@
* by default.
*
* @memberOf Benchmark.options
* @type boolean
* @type Boolean
*/
'async': false,
@@ -2190,14 +2208,14 @@
* A flag to indicate that the benchmark clock is deferred.
*
* @memberOf Benchmark.options
* @type boolean
* @type Boolean
*/
'defer': false,
/**
* The delay between test cycles (secs).
* @memberOf Benchmark.options
* @type number
* @type Number
*/
'delay': 0.005,
@@ -2206,7 +2224,7 @@
* (auto-generated if absent).
*
* @memberOf Benchmark.options
* @type string
* @type String
*/
'id': undefined,
@@ -2214,7 +2232,7 @@
* The default number of times to execute a test on a benchmark's first cycle.
*
* @memberOf Benchmark.options
* @type number
* @type Number
*/
'initCount': 1,
@@ -2224,7 +2242,7 @@
* Note: Cycle delays aren't counted toward the maximum time.
*
* @memberOf Benchmark.options
* @type number
* @type Number
*/
'maxTime': 5,
@@ -2232,7 +2250,7 @@
* The minimum sample size required to perform statistical analysis.
*
* @memberOf Benchmark.options
* @type number
* @type Number
*/
'minSamples': 5,
@@ -2240,7 +2258,7 @@
* The time needed to reduce the percent uncertainty of measurement to 1% (secs).
*
* @memberOf Benchmark.options
* @type number
* @type Number
*/
'minTime': 0,
@@ -2248,7 +2266,7 @@
* The name of the benchmark.
*
* @memberOf Benchmark.options
* @type string
* @type String
*/
'name': undefined,
@@ -2328,7 +2346,7 @@
*
* @static
* @memberOf Benchmark
* @type string
* @type String
*/
'version': '1.0.0'
});
@@ -2355,7 +2373,7 @@
* The number of times a test was executed.
*
* @memberOf Benchmark
* @type number
* @type Number
*/
'count': 0,
@@ -2363,7 +2381,7 @@
* The number of cycles performed while benchmarking.
*
* @memberOf Benchmark
* @type number
* @type Number
*/
'cycles': 0,
@@ -2371,7 +2389,7 @@
* The number of executions per second.
*
* @memberOf Benchmark
* @type number
* @type Number
*/
'hz': 0,
@@ -2379,7 +2397,7 @@
* The compiled test function.
*
* @memberOf Benchmark
* @type {Function|string}
* @type Function|String
*/
'compiled': undefined,
@@ -2395,7 +2413,7 @@
* The test to benchmark.
*
* @memberOf Benchmark
* @type {Function|string}
* @type Function|String
*/
'fn': undefined,
@@ -2403,7 +2421,7 @@
* A flag to indicate if the benchmark is aborted.
*
* @memberOf Benchmark
* @type boolean
* @type Boolean
*/
'aborted': false,
@@ -2411,7 +2429,7 @@
* A flag to indicate if the benchmark is running.
*
* @memberOf Benchmark
* @type boolean
* @type Boolean
*/
'running': false,
@@ -2419,7 +2437,7 @@
* Compiled into the test and executed immediately **before** the test loop.
*
* @memberOf Benchmark
* @type {Function|string}
* @type Function|String
* @example
*
* // basic usage
@@ -2482,7 +2500,7 @@
* Compiled into the test and executed immediately **after** the test loop.
*
* @memberOf Benchmark
* @type {Function|string}
* @type Function|String
*/
'teardown': noop,
@@ -2498,7 +2516,7 @@
* The margin of error.
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'moe': 0,
@@ -2506,7 +2524,7 @@
* The relative margin of error (expressed as a percentage of the mean).
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'rme': 0,
@@ -2514,7 +2532,7 @@
* The standard error of the mean.
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'sem': 0,
@@ -2522,7 +2540,7 @@
* The sample standard deviation.
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'deviation': 0,
@@ -2530,7 +2548,7 @@
* The sample arithmetic mean (secs).
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'mean': 0,
@@ -2546,7 +2564,7 @@
* The sample variance.
*
* @memberOf Benchmark#stats
* @type number
* @type Number
*/
'variance': 0
},
@@ -2563,7 +2581,7 @@
* The time taken to complete the last cycle (secs).
*
* @memberOf Benchmark#times
* @type number
* @type Number
*/
'cycle': 0,
@@ -2571,7 +2589,7 @@
* The time taken to complete the benchmark (secs).
*
* @memberOf Benchmark#times
* @type number
* @type Number
*/
'elapsed': 0,
@@ -2579,7 +2597,7 @@
* The time taken to execute the test once (secs).
*
* @memberOf Benchmark#times
* @type number
* @type Number
*/
'period': 0,
@@ -2587,7 +2605,7 @@
* A timestamp of when the benchmark started (ms).
*
* @memberOf Benchmark#times
* @type number
* @type Number
*/
'timeStamp': 0
}
@@ -2622,7 +2640,7 @@
* The number of deferred cycles performed while benchmarking.
*
* @memberOf Benchmark.Deferred
* @type number
* @type Number
*/
'cycles': 0,
@@ -2630,7 +2648,7 @@
* The time taken to complete the deferred benchmark (secs).
*
* @memberOf Benchmark.Deferred
* @type number
* @type Number
*/
'elapsed': 0,
@@ -2638,7 +2656,7 @@
* A timestamp of when the deferred benchmark started (ms).
*
* @memberOf Benchmark.Deferred
* @type number
* @type Number
*/
'timeStamp': 0
});
@@ -2655,7 +2673,7 @@
* A flag to indicate if the emitters listener iteration is aborted.
*
* @memberOf Benchmark.Event
* @type boolean
* @type Boolean
*/
'aborted': false,
@@ -2663,7 +2681,7 @@
* A flag to indicate if the default action is cancelled.
*
* @memberOf Benchmark.Event
* @type boolean
* @type Boolean
*/
'cancelled': false,
@@ -2695,7 +2713,7 @@
* A timestamp of when the event was created (ms).
*
* @memberOf Benchmark.Event
* @type number
* @type Number
*/
'timeStamp': 0,
@@ -2703,7 +2721,7 @@
* The event type.
*
* @memberOf Benchmark.Event
* @type string
* @type String
*/
'type': ''
});
@@ -2723,7 +2741,7 @@
* The name of the suite.
*
* @memberOf Benchmark.Suite.options
* @type string
* @type String
*/
'name': undefined
};
@@ -2736,7 +2754,7 @@
* The number of benchmarks in the suite.
*
* @memberOf Benchmark.Suite
* @type number
* @type Number
*/
'length': 0,
@@ -2744,7 +2762,7 @@
* A flag to indicate if the suite is aborted.
*
* @memberOf Benchmark.Suite
* @type boolean
* @type Boolean
*/
'aborted': false,
@@ -2752,7 +2770,7 @@
* A flag to indicate if the suite is running.
*
* @memberOf Benchmark.Suite
* @type boolean
* @type Boolean
*/
'running': false
});
@@ -2827,7 +2845,7 @@
/*--------------------------------------------------------------------------*/
// expose Benchmark
// some AMD build optimizers, like r.js, check for condition patterns like the following:
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// define as an anonymous module so, through path mapping, it can be aliased
define(['lodash', 'platform'], function(_, platform) {
@@ -2853,7 +2871,7 @@
}
// in a browser or Rhino
else {
root.Benchmark = Benchmark;
window.Benchmark = Benchmark;
}
}
}(this));

View File

@@ -1,24 +0,0 @@
Open Source Initiative OSI - The MIT License
http://www.opensource.org/licenses/mit-license.php
Copyright (c) 2010-2013 Brian Cavalier and John Hann
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.

View File

@@ -1,48 +0,0 @@
(function(){/*
MIT License (c) copyright 2010-2013 B Cavalier & J Hann MIT (c) copyright 2010-2013 B Cavalier & J Hann */
(function(f){function k(){}function g(a,e){return 0==T.call(a).indexOf("[object "+e)}function n(a){return a&&"/"==a.charAt(a.length-1)?a.substr(0,a.length-1):a}function d(a,e){var l,h,D,m;l=1;h=a;"."==h.charAt(0)&&(D=!0,h=h.replace(U,function(a,e,h,D){h&&l++;return D||""}));if(D){D=e.split("/");m=D.length-l;if(0>m)return a;D.splice(m,l);return D.concat(h||[]).join("/")}return h}function s(a){var e=a.indexOf("!");return{g:a.substr(e+1),d:0<=e&&a.substr(0,e)}}function v(){}function q(a,e){v.prototype=
a||Q;var l=new v;v.prototype=Q;for(var h in e)l[h]=e[h];return l}function y(){function a(a,e,l){h.push([a,e,l])}function e(a,e){for(var l,D=0;l=h[D++];)(l=l[a])&&l(e)}var l,h,D;l=this;h=[];D=function(l,m){a=l?function(a){a&&a(m)}:function(a,e){e&&e(m)};D=k;e(l?0:1,m);e=k;h=G};this.l=function(e,h,D){a(e,h,D);return l};this.k=function(a){l.H=a;D(!0,a)};this.e=function(a){l.Ba=a;D(!1,a)};this.F=function(a){e(2,a)}}function x(a){return a instanceof y||a instanceof u}function r(a,e,l,h){x(a)?a.l(e,l,h):
e(a)}function w(a,e,l){var h;return function(){0<=--a&&e&&(h=e.apply(G,arguments));0==a&&l&&l(h);return h}}function b(){var a,e;p="";a=[].slice.call(arguments);g(a[0],"Object")&&(e=a.shift(),e=c(e));return new u(a[0],a[1],a[2],e)}function c(a,e,l){var h;p="";if(a&&(t.V(a),E=t.b(a),"preloads"in a&&(h=new u(a.preloads,G,l,J,!0),t.n(function(){J=h})),a=a.main))return new u(a,e,l)}function u(a,e,l,h,D){var m;m=t.i(E,G,[].concat(a),D);this.then=this.l=a=function(a,e){r(m,function(e){a&&a.apply(G,e)},function(a){if(e)e(a);
else throw a;});return this};this.next=function(a,e,h){return new u(a,e,h,m)};this.config=c;(e||l)&&a(e,l);t.n(function(){r(D||J,function(){r(h,function(){t.A(m)},l)})})}function z(a){var e,l;e=a.id;e==G&&(K!==G?K={L:"Multiple anonymous defines encountered"}:(e=t.ja())||(K=a));if(e!=G){l=F[e];e in F||(l=t.o(e,E),l=t.I(l.b,e),F[e]=l);if(!x(l))throw Error("duplicate define: "+e);l.oa=!1;t.J(l,a)}}function A(){var a=t.ga(arguments);z(a)}var p,E,C,H,B=f.document,L=B&&(B.head||B.getElementsByTagName("head")[0]),
N=L&&L.getElementsByTagName("base")[0]||null,M={},I={},m={},V="addEventListener"in f?{}:{loaded:1,complete:1},Q={},T=Q.toString,G,F={},O={},J=!1,K,S=/^\/|^[^:]+:\/\//,U=/(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,W=/\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g,X=/require\s*\(\s*(["'])(.*?[^\\])\1\s*\)|[^\\]?(["'])/g,Y=/\s*,\s*/,R,t;t={t:function(a,e,l){var h;a=d(a,e);if("."==a.charAt(0))return a;h=s(a);a=(e=h.d)||h.g;a in l.c&&(a=l.c[a].Q||a);e&&(0>e.indexOf("/")&&!(e in l.c)&&(a=n(l.T)+"/"+e),a=a+"!"+h.g);return a},i:function(a,
e,l,h){function m(e,h){var l,c;l=t.t(e,b.id,a);if(!h)return l;c=s(l);if(!c.d)return l;l=F[c.d];c.g="normalize"in l?l.normalize(c.g,m,b.b)||"":m(c.g);return c.d+"!"+c.g}function c(e,l,d){var s;s=l&&function(a){l.apply(G,a)};if(g(e,"String")){if(s)throw Error("require(id, callback) not allowed");d=m(e,!0);e=F[d];if(!(d in F))throw Error("Module not resolved: "+d);return(d=x(e)&&e.a)||e}r(t.A(t.i(a,b.id,e,h)),s,d)}var b;b=new y;b.id=e||"";b.ka=h;b.K=l;b.b=a;b.s=c;c.toUrl=function(e){return t.o(m(e,!0),
a).url};b.t=m;return b},I:function(a,e,l){var h,m,c;h=t.i(a,e,G,l);m=h.k;c=w(1,function(a){h.w=a;try{return t.ba(h)}catch(e){h.e(e)}});h.k=function(a){r(l||J,function(){m(F[h.id]=O[h.url]=c(a))})};h.M=function(a){r(l||J,function(){h.a&&(c(a),h.F(I))})};return h},$:function(a,e,l,h){return t.i(a,l,G,h)},ia:function(a){return a.s},O:function(a){return a.a||(a.a={})},ha:function(a){var e=a.B;e||(e=a.B={id:a.id,uri:t.P(a),exports:t.O(a),config:function(){return a.b}},e.a=e.exports);return e},P:function(a){return a.url||
(a.url=t.u(a.s.toUrl(a.id),a.b))},V:function(a){var e,l,h,m,c;e="curl";l="define";h=m=f;if(a&&(c=a.overwriteApi||a.ya,e=a.apiName||a.qa||e,h=a.apiContext||a.pa||h,l=a.defineName||a.ua||l,m=a.defineContext||a.ta||m,C&&g(C,"Function")&&(f.curl=C),C=null,H&&g(H,"Function")&&(f.define=H),H=null,!c)){if(h[e]&&h[e]!=b)throw Error(e+" already exists");if(m[l]&&m[l]!=A)throw Error(l+" already exists");}h[e]=b;m[l]=A},b:function(a){function e(a,e){var l,h,b,p,f;for(f in a){b=a[f];g(b,"String")&&(b={path:a[f]});
b.name=b.name||f;p=m;h=s(n(b.name));l=h.g;if(h=h.d)p=c[h],p||(p=c[h]=q(m),p.c=q(m.c),p.f=[]),delete a[f];h=b;var k=e,r=void 0;h.path=n(h.path||h.location||"");k&&(r=h.main||"./main","."==r.charAt(0)||(r="./"+r),h.Q=d(r,h.name+"/"));h.b=h.config;h.b&&(h.b=q(m,h.b));h.W=l.split("/").length;l?(p.c[l]=h,p.f.push(l)):p.p=t.U(b.path,m)}}function l(a){var e=a.c;a.S=RegExp("^("+a.f.sort(function(a,h){return e[h].W-e[a].W}).join("|").replace(/\/|\./g,"\\$&")+")(?=\\/|$)");delete a.f}var h,m,c,b;"baseUrl"in
a&&(a.p=a.baseUrl);"main"in a&&(a.Q=a.main);"preloads"in a&&(a.za=a.preloads);"pluginPath"in a&&(a.T=a.pluginPath);if("dontAddFileExt"in a||a.j)a.j=RegExp(a.dontAddFileExt||a.j);h=E;m=q(h,a);m.c=q(h.c);c=a.plugins||{};m.plugins=q(h.plugins);m.D=q(h.D,a.D);m.C=q(h.C,a.C);m.f=[];e(a.packages,!0);e(a.paths,!1);for(b in c)a=t.t(b+"!","",m),m.plugins[a.substr(0,a.length-1)]=c[b];c=m.plugins;for(b in c)if(c[b]=q(m,c[b]),a=c[b].f)c[b].f=a.concat(m.f),l(c[b]);for(b in h.c)m.c.hasOwnProperty(b)||m.f.push(b);
l(m);return m},o:function(a,e){var m,h,b,c;m=e.c;b=S.test(a)?a:a.replace(e.S,function(a){h=m[a]||{};c=h.b;return h.path||""});return{b:c||E,url:t.U(b,e)}},U:function(a,e){var m=e.p;return m&&!S.test(a)?n(m)+"/"+a:a},u:function(a,e){return a+((e||E).j.test(a)?"":".js")},m:function(a,e,l){var h=B.createElement("script");h.onload=h.onreadystatechange=function(l){l=l||f.event;if("load"==l.type||V[h.readyState])delete m[a.id],h.onload=h.onreadystatechange=h.onerror="",e()};h.onerror=function(){l(Error("Syntax or http error: "+
a.url))};h.type=a.r||"text/javascript";h.charset="utf-8";h.async=!a.R;h.src=a.url;m[a.id]=h;L.insertBefore(h,N);return h},N:function(a){var e=[],m;("string"==typeof a?a:a.toSource?a.toSource():a.toString()).replace(W,"").replace(X,function(a,b,c,d){d?m=m==d?G:m:m||e.push(c);return""});return e},ga:function(a){var e,m,h,b,c,d;c=a.length;h=a[c-1];b=g(h,"Function")?h.length:-1;2==c?g(a[0],"Array")?m=a[0]:e=a[0]:3==c&&(e=a[0],m=a[1]);!m&&0<b&&(d=!0,m=["require","exports","module"].slice(0,b).concat(t.N(h)));
return{id:e,w:m||[],G:0<=b?h:function(){return h},v:d}},ba:function(a){var e;e=a.G.apply(a.v?a.a:G,a.w);e===G&&a.a&&(e=a.B?a.a=a.B.a:a.a);return e},J:function(a,e){a.G=e.G;a.v=e.v;a.K=e.w;t.A(a)},A:function(a){function e(a,e,m){d[e]=a;m&&s(a,e)}function m(e,h){var b,c,l,d;b=w(1,function(a){c(a);g(a,h)});c=w(1,function(a){s(a,h)});l=t.da(e,a);(d=x(l)&&l.a)&&c(d);r(l,b,a.e,a.a&&function(a){l.a&&(a==M?c(l.a):a==I&&b(l.a))})}function h(){a.k(d)}var b,c,d,p,f,s,g;d=[];c=a.K;p=c.length;0==c.length&&h();
s=w(p,e,function(){a.M&&a.M(d)});g=w(p,e,h);for(b=0;b<p;b++)f=c[b],f in R?(g(R[f](a),b,!0),a.a&&a.F(M)):f?m(f,b):g(G,b,!0);return a},ea:function(a){t.P(a);t.m(a,function(){var e=K;K=G;!1!==a.oa&&(!e||e.L?a.e(Error(e&&e.L||"define() missing or duplicated: "+a.url)):t.J(a,e))},a.e);return a},da:function(a,e){var m,h,b,c,d,p,f,g,q,k,n,u;m=e.t;h=e.ka;b=e.b||E;d=m(a);d in F?p=d:(c=s(d),g=c.g,p=c.d||g,q=t.o(p,b));if(!(d in F))if(u=t.o(g,b).b,c.d)f=p;else if(f=u.moduleLoader||u.xa||u.loader||u.wa)g=p,p=
f,q=t.o(f,b);p in F?k=F[p]:q.url in O?k=F[p]=O[q.url]:(k=t.I(u,p,h),k.url=t.u(q.url,q.b),F[p]=O[q.url]=k,t.ea(k));p==f&&(c.d&&b.plugins[c.d]&&(u=b.plugins[c.d]),n=new y,r(k,function(a){var e,b,c;c=a.dynamic;g="normalize"in a?a.normalize(g,m,k.b)||"":m(g);b=f+"!"+g;e=F[b];if(!(b in F)){e=t.$(u,b,g,h);c||(F[b]=e);var d=function(a){c||(F[b]=a);e.k(a)};d.resolve=d;d.reject=d.error=e.e;a.load(g,e.s,d,u)}n!=e&&r(e,n.k,n.e,n.F)},n.e));return n||k},ja:function(){var a;if(!g(f.opera,"Opera"))for(var e in m)if("interactive"==
m[e].readyState){a=e;break}return a},fa:function(a){var e=0,m,b;for(m=B&&(B.scripts||B.getElementsByTagName("script"));m&&(b=m[e++]);)if(a(b))return b},ca:function(){var a,e="";(a=t.fa(function(a){(a=a.getAttribute("data-curl-run"))&&(e=a);return a}))&&a.setAttribute("data-curl-run","");return e},X:function(){function a(){t.m({url:b.shift()},e,e)}function e(){p&&(b.length?(t.n(m),a()):m("run.js script did not run."))}function m(a){throw Error(a||"Primary run.js failed. Trying fallback.");}var b=p.split(Y);
b.length&&a()},n:function(a){setTimeout(a,0)}};R={require:t.ia,exports:t.O,module:t.ha};b.version="0.8.4";b.config=c;A.amd={plugins:!0,jQuery:!0,curl:"0.8.4"};E={p:"",T:"curl/plugin",j:/\?|\.js\b/,D:{},C:{},plugins:{},c:{},S:/$^/};C=f.curl;H=f.define;C&&g(C,"Object")?(f.curl=G,c(C)):t.V();(p=t.ca())&&t.n(t.X);F.curl=b;F["curl/_privileged"]={core:t,cache:F,config:function(){return E},_define:z,_curl:b,Promise:y}})(this.window||"undefined"!=typeof global&&global||this);
(function(f,k){function g(){if(!k.body)return!1;A||(A=k.createTextNode(""));try{return k.body.removeChild(k.body.appendChild(A)),A=z,!0}catch(b){return!1}}function n(){var d;d=v[k[s]]&&g();if(!x&&d){x=!0;for(clearTimeout(u);b=c.pop();)b();y&&(k[s]="complete");for(var f;f=q.shift();)f()}return d}function d(){n();x||(u=setTimeout(d,r))}var s="readyState",v={loaded:1,interactive:1,complete:1},q=[],y=k&&"string"!=typeof k[s],x=!1,r=10,w,b,c=[],u,z,A;w="addEventListener"in f?function(b,c){b.addEventListener(c,
n,!1);return function(){b.removeEventListener(c,n,!1)}}:function(b,c){b.attachEvent("on"+c,n);return function(){b.detachEvent(c,n)}};k&&!n()&&(c=[w(f,"load"),w(k,"readystatechange"),w(f,"DOMContentLoaded")],u=setTimeout(d,r));define("curl/domReady",function(){function b(c){x?c():q.push(c)}b.then=b;b.amd=!0;return b})})(this,this.document);var P;
(function(f,k){define("curl/shim/dojo18",["curl/_privileged"],function(g){function n(c){c.has||(c.has=b);c.on||(c.on=s);c.idle||(c.idle=d);c.async=!0}function d(){for(var b in q)if(q[b]instanceof y)return!1;return!0}function s(){}var v,q,y,x;v=g._curl;q=g.cache;y=g.Promise;x=g.core.i;var r,w,b;r=g.b().va||{};w=k&&k.createElement("div");b=function(b){return"function"==typeof r[b]?r[b]=r[b](f,k,w):r[b]};b.add=function(c,d,f,g){if(void 0===r[c]||g)r[c]=d;if(f)return b(c)};r["dojo-loader"]=!1;q["dojo/_base/loader"]=
0;"undefined"==typeof P&&(n(v),P=v);g.core.i=function(){var b=x.apply(this,arguments);n(b.s);return b};return!0})})("object"==typeof global?global:this.window||this.global,"object"==typeof document&&document);
(function(f,k,g){define("curl/plugin/js",["curl/_privileged"],function(f){function d(b,c,d){function s(){p||(k<new Date?d():setTimeout(s,10))}var k,p,q;k=(new Date).valueOf()+(b.na||3E5);d&&b.a&&setTimeout(s,10);q=f.core.m(b,function(){p=!0;b.a&&(b.H=g(b.a));!b.a||b.H?c(q):d()},function(b){p=!0;d(b)})}function s(b,c){d(b,function(){var d=q.shift();r=0<q.length;d&&s.apply(null,d);c.k(b.H||!0)},function(b){c.e(b)})}var v={},q=[],y=k&&!0==k.createElement("script").async,x,r,w=/\?|\.js\b/;x=f.Promise;
return{dynamic:!0,normalize:function(b,c){var d=b.indexOf("!");return 0<=d?c(b.substr(0,d))+b.substr(d):c(b)},load:function(b,c,f,g){function k(b){(f.error||function(b){throw b;})(b)}var p,n,C,H,B;p=0<b.indexOf("!order");n=b.indexOf("!exports=");C=0<n?b.substr(n+9):g.a;H="prefetch"in g?g.prefetch:!0;b=p||0<n?b.substr(0,b.indexOf("!")):b;n=(n=g.dontAddFileExt||g.j)?RegExp(n):w;B=c.toUrl(b);n.test(B)||(B=B.lastIndexOf(".")<=B.lastIndexOf("/")?B+".js":B);B in v?v[B]instanceof x?v[B].l(f,k):f(v[B]):(b=
{name:b,url:B,R:p,a:C,na:g.timeout},v[B]=c=new x,c.l(function(b){v[B]=b;f(b)},k),p&&!y&&r?(q.push([b,c]),H&&(b.r="text/cache",d(b,function(b){b&&b.parentNode.removeChild(b)},function(){}),b.r="")):(r=r||p,s(b,c)))},cramPlugin:"../cram/js"}})})(this,this.document,function(f){try{return eval(f)}catch(k){}});
define("curl/plugin/_fetchText",[],function(){var f,k;k=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];f=function(){if("undefined"!==typeof XMLHttpRequest)f=function(){return new XMLHttpRequest};else for(var g=f=function(){throw Error("getXhr(): XMLHttpRequest not available");};0<k.length&&f===g;)(function(g){try{new ActiveXObject(g),f=function(){return new ActiveXObject(g)}}catch(d){}})(k.shift());return f()};return function(g,k,d){var s=f();s.open("GET",g,!0);s.onreadystatechange=function(){4===
s.readyState&&(400>s.status?k(s.responseText):d(Error("fetchText() failed. status: "+s.statusText)))};s.send(null)}});define("curl/plugin/text",["./_fetchText"],function(f){function k(f){throw f;}return{load:function(g,n,d){f(n.toUrl(g),d,d.error||k)},cramPlugin:"../cram/text"}});
define("curl/plugin/async",function(){return{load:function(f,k,g){function n(d){"function"==typeof g.error&&g.error(d)}k([f],function(d){"function"==typeof d.l?d.l(function(f){0==arguments.length&&(f=d);g(f)},n):g(d)},g.error||function(d){throw d;})},analyze:function(f,k,g){g(f)}}});
(function(f){function k(){var b;b=p[z]("link");b.rel="stylesheet";b.type="text/css";return b}function g(b,c){b.onload=function(){I.load=I.load||!0;c()}}function n(b,c){b.onerror=function(){I.error=I.error||!0;c()}}function d(b,c,d){B.push({url:b,Y:c,aa:function(){d(Error(M))}});(b=v())&&s(b)}function s(b){var c,d;c=B.shift();d=b.styleSheet;c?(b.onload=function(){c.Y(c.ma);s(b)},b.onerror=function(){c.aa();s(b)},c.ma=d.imports[d.addImport(c.url)]):(b.onload=b.onerror=u,H.push(b))}function v(){var b;
b=H.shift();!b&&C.length<L&&(b=p.createElement("style"),C.push(b),E.appendChild(b));return b}function q(b){var c,d,f;if(!b.href||p.readyState&&"complete"!=p.readyState)return!1;c=!1;try{if(d=b.sheet)f=d.cssRules,c=null===f,!c&&f&&(d.insertRule("-curl-css-test {}",0),d.deleteRule(0),c=!0)}catch(g){c="[object Opera]"!=Object.prototype.toString.call(window.opera)&&/security|denied/i.test(g.message)}return c}function y(b,c,d){I.load||(q(b)?d(b.sheet):b.onload==u||!b.onload||A(function(){y(b,c,d)},c))}
function x(c,d,f){function k(){c.onload!=u&&c.onload&&(c.onload=c.onerror=u,b(function(){f(c.sheet)}))}g(c,k);y(c,d,k)}function r(b,c){n(b,function(){b.onload!=u&&b.onload&&(b.onload=b.onerror=u,c(Error(M)))})}function w(b,c,d,f){var g;g=k();x(g,f,c);r(g,d);g.href=b;E.appendChild(g)}function b(b){function c(){p.readyState&&"complete"!=p.readyState?A(c,10):b()}c()}function c(b){return b.lastIndexOf(".")<=b.lastIndexOf("/")?b+".css":b}function u(){}var z="createElement",A=f.setTimeout,p=f.document,
E;f=p&&p.createStyleSheet&&!(10<=p.documentMode);var C=[],H=[],B=[],L=12,N,M="HTTP or network error.",I={};p&&(E=p.head||p.getElementsByTagName("head")[0],N=f?d:w);define("curl/plugin/css",{normalize:function(b,c){var d,f;if(!b)return b;d=b.split(",");f=[];for(var g=0,k=d.length;g<k;g++)f.push(c(d[g]));return f.join(",")},load:function(b,d,f,g){function p(b){1<n.length&&q.push(b);0==--C&&f(1==n.length?b:q)}function s(b){(f.e||function(b){throw b;})(b)}var q,n,r,C,w;q=[];n=(b||"").split(",");r=g.cssWatchPeriod||
50;g=g.cssNoWait;C=n.length;for(w=0;w<n.length;w++){b=n[w];var u;b=c(d.toUrl(b));g?(u=k(),u.href=b,E.appendChild(u),p(u.sheet||u.styleSheet)):N(b,p,s,r)}},cramPlugin:"../cram/css"})})(this);
(function(f){var k=f.document,g=/^\/\//,n;k&&(n=k.head||(k.head=k.getElementsByTagName("head")[0]));define("curl/plugin/link",{load:function(d,f,v,q){d=f.toUrl(d);d=d.lastIndexOf(".")<=d.lastIndexOf("/")?d+".css":d;q=d=(q="fixSchemalessUrls"in q?q.fixSchemalessUrls:k.location.protocol)?d.replace(g,q+"//"):d;d=k.createElement("link");d.rel="stylesheet";d.type="text/css";d.href=q;n.appendChild(d);v(d.sheet||d.styleSheet)}})})(this);
define("curl/plugin/domReady",["../domReady"],function(f){return{load:function(k,g,n){f(n)}}});(function(f){define("curl/shim/_fetchText",function(){function k(d,f,g){n.Aa(d,function(d,k){d?g(d):f(k.toString())})}function g(f,g,k){var n;f=s.parse(f,!1,!0);n="";d.get(f,function(d){d.h("data",function(b){n+=b}).h("end",function(){g(n)}).h("error",k)}).h("error",k)}var n,d,s;n=f("fs");d=f("http");s=f("url");var v;v=/^https?:/;return function(d,f,n){v.test(d)?g(d,f,n):k(d,f,n)}})})(P);define.amd.Da=!0;
(function(f,k){define("curl/shim/ssjs",["curl/_privileged","./_fetchText"],function(g,n){function d(b,c,d){try{k(b.url),c()}catch(f){d(f)}}function s(b,c,d){var g;try{g=b.url.replace(/\.js$/,""),f(g),c()}catch(k){d(k)}}function v(b,c,d){var g;b=f("url").parse(b.url,!1,!0);g="";z.get(b,function(b){b.h("data",function(b){g+=b}).h("end",function(){y(g);c()}).h("error",d)}).h("error",d)}function q(b){throw Error("ssjs: unable to load module in current environment: "+b.url);}function y(b){eval(b)}function x(b){return b&&
b.replace(c,function(b,c){return c})}var r,w,b,c,u,z,A,p;if("object"!=typeof window||!window.sa&&!window.navigator){r=g.ra;w=g.b();b=/^\w+:\/\//;c=/(^\w+:)?.*$/;"undefined"==typeof XMLHttpRequest&&(r["curl/plugin/_fetchText"]=n);u=(w.q&&":"!=w.q[w.q.length-1]?w.q+":":w.q)||x(w.p)||"http:";if(k)A=p=d;else if(f){A=s;try{z=f("http"),p=v}catch(E){p=q}}else A=p=q;"object"===typeof process&&process.la&&(g.Z.n=process.la);g.Z.m=function(c,d,f){/^\/\//.test(c.url)&&(c.url=u+c.url);return b.test(c.url)?p(c,
d,f):A(c,d,f)}}})})(P,void 0);
(function(f,k,g){define("curl/loader/cjsm11",["../plugin/_fetchText","curl/_privileged"],function(f,d){function s(d,b){s="text"in d?function(b,d){b.text=d}:function(b,d){b.appendChild(k.createTextNode(d))};s(d,b)}function v(d,b,c){c=c?"/*\n////@ sourceURL="+c.replace(/\s/g,"%20")+".js\n*/":"";return"define('"+b+"',['require','exports','module'],function(require,exports,module){"+d+"\n});\n"+c+"\n"}var q,y,x,r;y=(q=k&&(k.head||k.getElementsByTagName("head")[0]))&&q.getElementsByTagName("base")[0]||null;
x=d.core.N;r=d.core.u;v.load=function(d,b,c,u){var z,A,p;z=c.error||function(b){throw b;};A=r(b.Fa(d),u);p=!1!==u.injectSourceUrl&&A;f(A,function(f){var n;n=x(f);b(n,function(){f=v(f,d,p);if(u.injectScript){var n=f,r=k.createElement("script");s(r,n);r.charset="utf-8";q.insertBefore(r,y)}else g(f);c(b(d))},z)},z)};v.cramPlugin="../cram/cjsm11";return v})})(this,this.document,function(f){eval(f)});
define("curl/plugin/locale",function(){function f(f,d){var g;if(f&&(g=f.locale,"function"==typeof g&&(g=g(f,d)),"string"==typeof g))return g;if("undefined"==typeof window)return!1;g=window.clientInformation||window.navigator;return(g&&(g.language||g.userLanguage)||"").toLowerCase()}function k(f,d){return f.replace(g,(d?"/"+d:"")+"$&")}var g;g=/(\.js)?$/;f.toModuleId=k;f.load=function(g,d,s,v){function q(){var b=Error("Unable to find correct locale for "+g);if(s.error)s.error(b);else throw b;}var y,
x;y=f(v,g);x=v.localeToModuleId||k;v=y?x(g,y):g;try{s(d(v))}catch(r){x=y?x(g,!1):g;if(x==v)return q();try{s(d(x))}catch(w){if(!0!==y)return q();d(["i18n!"+g],s,q)}}};return f});
define("curl/plugin/i18n",["./locale"],function(f){function k(f,k,d,s,v){f([k],function(f){s(f,d)},v)}return{load:function(g,n,d,s){function v(b,c){w[c]=b;q()}function q(){var f;if(++b==c.length)if(0==w.length)y(Error('No i18n bundles found: "'+g+'", locale "'+r+'"'));else{f=w[0]||{};for(z=1;z<w.length;z++){var k=w[z],n={},q=void 0;for(q in f)n[q]=f[q];if(k)for(q in k)n[q]=k[q];f=n}d(f)}}var y,x,r,w,b,c,u,z;y=d.error;g||y(Error("blank i18n bundle id."));x=s.localeToModuleId||f.Ea;r=f(s,g);c=[g];w=
[];b=0;if(r&&!1!==s.locale)for(c=c.concat(r.split("-")),u=[],z=1;z<c.length;z++)u[z-1]=c[z],s=x(g,u.join("-")),k(n,s,z,v,q);k(n,g,0,v,q)},cramPlugin:"../cram/i18n"}});
(function(f,k,g){define("curl/loader/legacy",["curl/_privileged"],function(n){var d,s,v;d=k&&!0==k.createElement("script").async;s=n.core.m;v=/\?|\.js\b/;return{load:function(k,n,x,r){function w(){E.r="";s(E,b,c)}function b(){var b;if(!(0<--C)){if(z)try{b=z.call(f,k)}catch(d){c(Error("Factory for legacy "+k+" failed: "+d.message))}else try{b=g(u)}catch(n){c(Error("Failed to find exports "+u+" for legacy "+k))}define(k,b);x(b)}}function c(b){(x.error||function(b){throw b;})(b)}var u,z,A,p,E,C;u=r.exports||
r.a;z=r.factory||r.factory;if(!u&&!z)throw Error("`exports` or `factory` required for legacy: "+k);A=[].concat(r.requires||r.Ca||[]);r=(r=r.dontAddFileExt||r.j)?RegExp(r):v;p=n.toUrl(k);r.test(p)||(p=p.lastIndexOf(".")<=p.lastIndexOf("/")?p+".js":p);E={url:p,R:!0,r:d||!A.length?"":"text/cache"};A.length?(C=2,n(A,d?b:w,c)):C=1;s(E,b,c)},cramPlugin:"../cram/legacy"}})})(this,this.document,function(f){return(0,eval)(f)});
}).call(this);

35
vendor/docdown/README.md vendored Normal file
View File

@@ -0,0 +1,35 @@
# Docdown <sup>v1.0.0</sup>
A simple JSDoc to Markdown documentation generator.
## Documentation
The documentation for Docdown can be viewed here: [/doc/README.md](https://github.com/jdalton/docdown/blob/master/doc/README.md#readme)
For a list of upcoming features, check out our [roadmap](https://github.com/jdalton/docdown/wiki/Roadmap).
## Installation and usage
Usage example:
```php
require("docdown.php");
// generate Markdown
$markdown = docdown(array(
"path" => $filepath,
"url" => "https://github.com/username/project/blob/master/my.js"
));
```
## Author
| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
|---|
| [John-David Dalton](http://allyoucanleet.com/) |
## Contributors
| [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](http://mathiasbynens.be/) |

View File

@@ -4,13 +4,13 @@
* Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit>
*/
require(dirname(__FILE__) . '/src/DocDown/MarkdownGenerator.php');
require(dirname(__FILE__) . '/src/DocDown/Generator.php');
/**
* Generates Markdown from JSDoc entries in a given file.
*
* @param {Array} [$options=array()] The options array.
* @returns {string} The generated Markdown.
* @returns {String} The generated Markdown.
* @example
*
* // specify a file path
@@ -32,7 +32,7 @@ require(dirname(__FILE__) . '/src/DocDown/MarkdownGenerator.php');
* ));
*/
function docdown( $options = array() ) {
$gen = new MarkdownGenerator($options);
$gen = new Generator($options);
return $gen->generate();
}
?>

View File

@@ -19,7 +19,7 @@ class Alias {
* The Alias constructor.
*
* @constructor
* @param {string} $name The alias name.
* @param {String} $name The alias name.
* @param {Object} $owner The alias owner.
*/
public function __construct( $name, $owner ) {
@@ -47,8 +47,8 @@ class Alias {
* Extracts the entry's `alias` objects.
*
* @memberOf Alias
* @param {number} $index The index of the array value to return.
* @returns {Array|string} The entry's `alias` objects.
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry's `alias` objects.
*/
public function getAliases( $index = null ) {
$result = array();
@@ -61,7 +61,7 @@ class Alias {
* Extracts the function call from the owner entry.
*
* @memberOf Alias
* @returns {string} The function call.
* @returns {String} The function call.
*/
public function getCall() {
return $this->_call;
@@ -71,7 +71,7 @@ class Alias {
* Extracts the owner entry's `category` data.
*
* @memberOf Alias
* @returns {string} The owner entry's `category` data.
* @returns {String} The owner entry's `category` data.
*/
public function getCategory() {
return $this->_category;
@@ -81,7 +81,7 @@ class Alias {
* Extracts the owner entry's description.
*
* @memberOf Alias
* @returns {string} The owner entry's description.
* @returns {String} The owner entry's description.
*/
public function getDesc() {
return $this->_desc;
@@ -91,7 +91,7 @@ class Alias {
* Extracts the owner entry's `example` data.
*
* @memberOf Alias
* @returns {string} The owner entry's `example` data.
* @returns {String} The owner entry's `example` data.
*/
public function getExample() {
return $this->_example;
@@ -101,7 +101,7 @@ class Alias {
* Checks if the entry is an alias.
*
* @memberOf Alias
* @returns {boolean} Returns `true`.
* @returns {Boolean} Returns `true`.
*/
public function isAlias() {
return true;
@@ -111,7 +111,7 @@ class Alias {
* Checks if the owner entry is a constructor.
*
* @memberOf Alias
* @returns {boolean} Returns `true` if a constructor, else `false`.
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
return $this->_isCtor;
@@ -121,7 +121,7 @@ class Alias {
* Checks if the owner entry is a license.
*
* @memberOf Alias
* @returns {boolean} Returns `true` if a license, else `false`.
* @returns {Boolean} Returns `true` if a license, else `false`.
*/
public function isLicense() {
return $this->_isLicense;
@@ -131,7 +131,7 @@ class Alias {
* Checks if the owner entry *is* assigned to a prototype.
*
* @memberOf Alias
* @returns {boolean} Returns `true` if assigned to a prototype, else `false`.
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
return $this->_isPlugin;
@@ -141,7 +141,7 @@ class Alias {
* Checks if the owner entry is private.
*
* @memberOf Alias
* @returns {boolean} Returns `true` if private, else `false`.
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
return $this->_isPrivate;
@@ -151,7 +151,7 @@ class Alias {
* Checks if the owner entry is *not* assigned to a prototype.
*
* @memberOf Alias
* @returns {boolean} Returns `true` if not assigned to a prototype, else `false`.
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
return $this->_isStatic;
@@ -161,7 +161,7 @@ class Alias {
* Resolves the owner entry's line number.
*
* @memberOf Alias
* @returns {number} The owner entry's line number.
* @returns {Number} The owner entry's line number.
*/
public function getLineNumber() {
return $this->_lineNumber;
@@ -171,8 +171,8 @@ class Alias {
* Extracts the owner entry's `member` data.
*
* @memberOf Alias
* @param {number} $index The index of the array value to return.
* @returns {Array|string} The owner entry's `member` data.
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The owner entry's `member` data.
*/
public function getMembers( $index = null ) {
return $index !== null
@@ -184,7 +184,7 @@ class Alias {
* Extracts the owner entry's `name` data.
*
* @memberOf Alias
* @returns {string} The owner entry's `name` data.
* @returns {String} The owner entry's `name` data.
*/
public function getName() {
return $this->_name;
@@ -194,7 +194,7 @@ class Alias {
* Extracts the owner entry's `param` data.
*
* @memberOf Alias
* @param {number} $index The index of the array value to return.
* @param {Number} $index The index of the array value to return.
* @returns {Array} The owner entry's `param` data.
*/
public function getParams( $index = null ) {
@@ -207,7 +207,7 @@ class Alias {
* Extracts the owner entry's `returns` data.
*
* @memberOf Alias
* @returns {string} The owner entry's `returns` data.
* @returns {String} The owner entry's `returns` data.
*/
public function getReturns() {
return $this->_returns;
@@ -217,7 +217,7 @@ class Alias {
* Extracts the owner entry's `type` data.
*
* @memberOf Alias
* @returns {string} The owner entry's `type` data.
* @returns {String} The owner entry's `type` data.
*/
public function getType() {
return $this->_type;

View File

@@ -11,7 +11,7 @@ class Entry {
* The documentation entry.
*
* @memberOf Entry
* @type string
* @type String
*/
public $entry = '';
@@ -19,7 +19,7 @@ class Entry {
* The language highlighter used for code examples.
*
* @memberOf Entry
* @type string
* @type String
*/
public $lang = '';
@@ -27,7 +27,7 @@ class Entry {
* The source code.
*
* @memberOf Entry
* @type string
* @type String
*/
public $source = '';
@@ -37,9 +37,9 @@ class Entry {
* The Entry constructor.
*
* @constructor
* @param {string} $entry The documentation entry to analyse.
* @param {string} $source The source code.
* @param {string} [$lang ='js'] The language highlighter used for code examples.
* @param {String} $entry The documentation entry to analyse.
* @param {String} $source The source code.
* @param {String} [$lang ='js'] The language highlighter used for code examples.
*/
public function __construct( $entry, $source, $lang = 'js' ) {
$this->entry = $entry;
@@ -54,7 +54,7 @@ class Entry {
*
* @static
* @memberOf Entry
* @param {string} $source The source code.
* @param {String} $source The source code.
* @returns {Array} The array of entries.
*/
public static function getEntries( $source ) {
@@ -69,7 +69,7 @@ class Entry {
*
* @private
* @memberOf Entry
* @returns {boolean} Returns `true` if the entry is a function reference, else `false`.
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
*/
private function isFunction() {
if (!isset($this->_isFunction)) {
@@ -89,8 +89,8 @@ class Entry {
* Extracts the entry's `alias` objects.
*
* @memberOf Entry
* @param {number} $index The index of the array value to return.
* @returns {Array|string} The entry's `alias` objects.
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry's `alias` objects.
*/
public function getAliases( $index = null ) {
if (!isset($this->_aliases)) {
@@ -116,7 +116,7 @@ class Entry {
* Extracts the function call from the entry.
*
* @memberOf Entry
* @returns {string} The function call.
* @returns {String} The function call.
*/
public function getCall() {
if (isset($this->_call)) {
@@ -140,15 +140,12 @@ class Entry {
// compose parts
$result = array($result);
$params = $this->getParams();
foreach ($params as $param) {
// skip params that are properties of other params (e.g. `options.leading`)
if (!preg_match('/\w+\.[\w.]+\s*=/', $param[1])) {
$result[] = $param[1];
}
$result[] = $param[1];
}
// format
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
}
$this->_call = $result ? $result : $name;
@@ -159,7 +156,7 @@ class Entry {
* Extracts the entry's `category` data.
*
* @memberOf Entry
* @returns {string} The entry's `category` data.
* @returns {String} The entry's `category` data.
*/
public function getCategory() {
if (isset($this->_category)) {
@@ -180,7 +177,7 @@ class Entry {
* Extracts the entry's description.
*
* @memberOf Entry
* @returns {string} The entry's description.
* @returns {String} The entry's description.
*/
public function getDesc() {
if (isset($this->_desc)) {
@@ -204,7 +201,7 @@ class Entry {
* Extracts the entry's `example` data.
*
* @memberOf Entry
* @returns {string} The entry's `example` data.
* @returns {String} The entry's `example` data.
*/
public function getExample() {
if (isset($this->_example)) {
@@ -224,7 +221,7 @@ class Entry {
* Checks if the entry is an alias.
*
* @memberOf Entry
* @returns {boolean} Returns `false`.
* @returns {Boolean} Returns `false`.
*/
public function isAlias() {
return false;
@@ -234,7 +231,7 @@ class Entry {
* Checks if the entry is a constructor.
*
* @memberOf Entry
* @returns {boolean} Returns `true` if a constructor, else `false`.
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
if (!isset($this->_isCtor)) {
@@ -247,7 +244,7 @@ class Entry {
* Checks if the entry is a license.
*
* @memberOf Entry
* @returns {boolean} Returns `true` if a license, else `false`.
* @returns {Boolean} Returns `true` if a license, else `false`.
*/
public function isLicense() {
if (!isset($this->_isLicense)) {
@@ -260,7 +257,7 @@ class Entry {
* Checks if the entry *is* assigned to a prototype.
*
* @memberOf Entry
* @returns {boolean} Returns `true` if assigned to a prototype, else `false`.
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
if (!isset($this->_isPlugin)) {
@@ -273,7 +270,7 @@ class Entry {
* Checks if the entry is private.
*
* @memberOf Entry
* @returns {boolean} Returns `true` if private, else `false`.
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
if (!isset($this->_isPrivate)) {
@@ -286,7 +283,7 @@ class Entry {
* Checks if the entry is *not* assigned to a prototype.
*
* @memberOf Entry
* @returns {boolean} Returns `true` if not assigned to a prototype, else `false`.
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
if (isset($this->_isStatic)) {
@@ -318,7 +315,7 @@ class Entry {
* Resolves the entry's line number.
*
* @memberOf Entry
* @returns {number} The entry's line number.
* @returns {Number} The entry's line number.
*/
public function getLineNumber() {
if (!isset($this->_lineNumber)) {
@@ -332,8 +329,8 @@ class Entry {
* Extracts the entry's `member` data.
*
* @memberOf Entry
* @param {number} $index The index of the array value to return.
* @returns {Array|string} The entry's `member` data.
* @param {Number} $index The index of the array value to return.
* @returns {Array|String} The entry's `member` data.
*/
public function getMembers( $index = null ) {
if (!isset($this->_members)) {
@@ -354,7 +351,7 @@ class Entry {
* Extracts the entry's `name` data.
*
* @memberOf Entry
* @returns {string} The entry's `name` data.
* @returns {String} The entry's `name` data.
*/
public function getName() {
if (isset($this->_name)) {
@@ -375,26 +372,23 @@ class Entry {
* Extracts the entry's `param` data.
*
* @memberOf Entry
* @param {number} $index The index of the array value to return.
* @param {Number} $index The index of the array value to return.
* @returns {Array} The entry's `param` data.
*/
public function getParams( $index = null ) {
if (!isset($this->_params)) {
preg_match_all('#\*[\t ]*@param\s+\{\(?([^})]+)\)?\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $matchTuples);
$matchTuples = array_filter(array_slice($matchTuples, 1));
$result = array();
if (count($matchTuples)) {
foreach ($matchTuples as $tupleKey => $tuple) {
foreach ($tuple as $key => $value) {
if (!isset($result[$key])) {
$result[$key] = array();
preg_match_all('#\*[\t ]*@param\s+\{([^}]+)\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
if (count($result = array_filter(array_slice($result, 1)))) {
// repurpose array
foreach ($result as $param) {
foreach ($param as $key => $value) {
if (!is_array($result[0][$key])) {
$result[0][$key] = array();
}
$result[$key][] = $tupleKey
? trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]*/', ' ', $value))
: trim($value);
$result[0][$key][] = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]*/', ' ', $value));
}
}
$result = $result[0];
}
$this->_params = $result;
}
@@ -407,7 +401,7 @@ class Entry {
* Extracts the entry's `returns` data.
*
* @memberOf Entry
* @returns {string} The entry's `returns` data.
* @returns {String} The entry's `returns` data.
*/
public function getReturns() {
if (isset($this->_returns)) {
@@ -428,21 +422,18 @@ class Entry {
* Extracts the entry's `type` data.
*
* @memberOf Entry
* @returns {string} The entry's `type` data.
* @returns {String} The entry's `type` data.
*/
public function getType() {
if (isset($this->_type)) {
return $this->_type;
}
preg_match('#\*[\t ]*@type\s(?:\{\(?)?([^)}\n]+)#', $this->entry, $result);
preg_match('#\*[\t ]*@type\s+(.+)#', $this->entry, $result);
if (count($result)) {
$result = trim($result[1]);
if (preg_match('/^(?:array|function|object|regexp)$/', $result)) {
$result = ucfirst($result);
}
$result = trim(preg_replace('/(?:^|\n)[\t ]*\*[\t ]?/', ' ', $result[1]));
} else {
$result = $this->isFunction() ? 'Function' : 'unknown';
$result = $this->isFunction() ? 'Function' : 'Unknown';
}
$this->_type = $result;
return $result;

View File

@@ -5,21 +5,21 @@ require(dirname(__FILE__) . "/Entry.php");
/**
* Generates Markdown from JSDoc entries.
*/
class MarkdownGenerator {
class Generator {
/**
* The HTML for the close tag.
*
* @static
* @memberOf MarkdownGenerator
* @type string
* @memberOf Generator
* @type String
*/
public $closeTag = "\n<!-- /div -->\n";
/**
* An array of JSDoc entries.
*
* @memberOf MarkdownGenerator
* @memberOf Generator
* @type Array
*/
public $entries = array();
@@ -28,15 +28,15 @@ class MarkdownGenerator {
* The HTML for the open tag.
*
* @static
* @memberOf MarkdownGenerator
* @type string
* @memberOf Generator
* @type String
*/
public $openTag = "\n<!-- div -->\n";
/**
* An options array used to configure the generator.
*
* @memberOf MarkdownGenerator
* @memberOf Generator
* @type Array
*/
public $options = array();
@@ -44,18 +44,18 @@ class MarkdownGenerator {
/**
* The file's source code.
*
* @memberOf MarkdownGenerator
* @type string
* @memberOf Generator
* @type String
*/
public $source = '';
/*--------------------------------------------------------------------------*/
/**
* The MarkdownGenerator constructor.
* The Generator constructor.
*
* @constructor
* @param {string} $source The source code to parse.
* @param {String} $source The source code to parse.
* @param {Array} $options The options array.
*/
public function __construct( $source, $options = array() ) {
@@ -103,9 +103,9 @@ class MarkdownGenerator {
*
* @private
* @static
* @memberOf MarkdownGenerator
* @param {string} $string The string to format.
* @returns {string} The formatted string.
* @memberOf Generator
* @param {String} $string The string to format.
* @returns {String} The formatted string.
*/
private static function format( $string ) {
$counter = 0;
@@ -132,43 +132,28 @@ class MarkdownGenerator {
return trim($string);
}
/**
* Escapes special Markdown characters.
*
* @private
* @memberOf Entry
* @param {string} $string The string to escape.
* @returns {string} Returns the escaped string.
*/
private function escape( $string ) {
$string = preg_replace('/(?<!\\\)\*/', '&#42;', $string);
$string = preg_replace('/(?<!\\\)\[/', '&#91;', $string);
$string = preg_replace('/(?<!\\\)\]/', '&#93;', $string);
return $string;
}
/**
* Modify a string by replacing named tokens with matching assoc. array values.
*
* @private
* @static
* @memberOf MarkdownGenerator
* @param {string} $string The string to modify.
* @memberOf Generator
* @param {String} $string The string to modify.
* @param {Array|Object} $object The template object.
* @returns {string} The modified string.
* @returns {String} The modified string.
*/
private static function interpolate( $string, $object ) {
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
$tokens = array_unique(array_pop($tokens));
foreach ($tokens as $token) {
$pattern = '/#\{' . preg_replace('/([.*+?^${}()|[\]\\\])/', '\\\$1', $token) . '\}/';
$pattern = '/#\{' . $token . '\}/';
$replacement = '';
if (is_object($object)) {
preg_match('/\(([^)]+?)\)$/', $token, $args);
$args = preg_split('/,\s*/', array_pop($args));
$method = 'get' . ucfirst(preg_replace('/\([^)]+?\)$/', '', $token));
$method = 'get' . ucfirst(str_replace('/\([^)]+?\)$/', '', $token));
if (method_exists($object, $method)) {
$replacement = (string) call_user_func_array(array($object, $method), $args);
@@ -180,7 +165,7 @@ class MarkdownGenerator {
}
$string = preg_replace($pattern, trim($replacement), $string);
}
return MarkdownGenerator::format($string);
return Generator::format($string);
}
/*--------------------------------------------------------------------------*/
@@ -189,7 +174,7 @@ class MarkdownGenerator {
* Adds the given `$entries` to the `$result` array.
*
* @private
* @memberOf MarkdownGenerator
* @memberOf Generator
* @param {Array} $result The result array to modify.
* @param {Array} $entries The entries to add to the `$result`.
*/
@@ -203,21 +188,14 @@ class MarkdownGenerator {
array_push(
$result,
$this->openTag,
MarkdownGenerator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [&#x24C8;](#{href} \"View in source\") [&#x24C9;][1]\n\n#{desc}", array(
'call' => $entry->getCall(),
'desc' => $this->escape($entry->getDesc()),
'hash' => $entry->hash,
'href' => $entry->href,
'member' => $entry->member,
'separator' => $entry->separator
))
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [&#x24C8;](#{href} \"View in source\") [&#x24C9;][1]\n\n#{desc}", $entry)
);
// @alias
if (count($aliases = $entry->getAliases())) {
array_push($result, '', '#### Aliases');
foreach ($aliases as $index => $alias) {
$aliases[$index] = MarkdownGenerator::interpolate('#{member}#{separator}#{name}', $alias);
$aliases[$index] = $alias->getName();
}
$result[] = '*' . implode(', ', $aliases) . '*';
}
@@ -225,11 +203,11 @@ class MarkdownGenerator {
if (count($params = $entry->getParams())) {
array_push($result, '', '#### Arguments');
foreach ($params as $index => $param) {
$result[] = MarkdownGenerator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
'desc' => $this->escape($param[2]),
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
'desc' => $param[2],
'name' => $param[1],
'num' => $index + 1,
'type' => $this->escape($param[0])
'type' => $param[0]
));
}
}
@@ -238,10 +216,7 @@ class MarkdownGenerator {
array_push(
$result, '',
'#### Returns',
MarkdownGenerator::interpolate('(#{type}): #{desc}', array(
'desc' => $this->escape($returns[1]),
'type' => $this->escape($returns[0])
))
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
);
}
// @example
@@ -256,19 +231,18 @@ class MarkdownGenerator {
* Resolves the entry's hash used to navigate the documentation.
*
* @private
* @memberOf MarkdownGenerator
* @param {number|Object} $entry The entry object.
* @param {string} $member The name of the member.
* @returns {string} The url hash.
* @memberOf Generator
* @param {Number|Object} $entry The entry object.
* @param {String} $member The name of the member.
* @returns {String} The url hash.
*/
private function getHash( $entry, $member = '' ) {
$entry = is_numeric($entry) ? $this->entries[$entry] : $entry;
$member = !$member ? $entry->getMembers(0) : $member;
$result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall();
$result = preg_replace('/\(\[|\[\]/', '', $result);
$result = preg_replace('/[\t =|\'"{}.()\]]/', '', $result);
$result = preg_replace('/[\[#,]+/', '-', $result);
$result = preg_replace('/[ =|\'"{}.()\]]/', '', $result);
$result = preg_replace('/[[#,]/', '-', $result);
return strtolower($result);
}
@@ -276,9 +250,9 @@ class MarkdownGenerator {
* Resolves the entry's url for the specific line number.
*
* @private
* @memberOf MarkdownGenerator
* @param {number|Object} $entry The entry object.
* @returns {string} The url.
* @memberOf Generator
* @param {Number|Object} $entry The entry object.
* @returns {String} The url.
*/
private function getLineUrl( $entry ) {
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
@@ -289,9 +263,9 @@ class MarkdownGenerator {
* Extracts the character used to separate the entry's name from its member.
*
* @private
* @memberOf MarkdownGenerator
* @param {number|Object} $entry The entry object.
* @returns {string} The separator.
* @memberOf Generator
* @param {Number|Object} $entry The entry object.
* @returns {String} The separator.
*/
private function getSeparator( $entry ) {
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
@@ -303,8 +277,8 @@ class MarkdownGenerator {
/**
* Generates Markdown from JSDoc entries.
*
* @memberOf MarkdownGenerator
* @returns {string} The rendered Markdown.
* @memberOf Generator
* @returns {String} The rendered Markdown.
*/
public function generate() {
$api = array();
@@ -369,10 +343,9 @@ class MarkdownGenerator {
foreach ($api as $entry) {
$entry->hash = $this->getHash($entry);
$entry->href = $this->getLineUrl($entry);
$entry->separator = '';
$member = $entry->getMembers(0);
$member = ($member ? $member . $this->getSeparator($entry) : '') . $entry->getName();
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
// add properties to static and plugin sub-entries
@@ -471,7 +444,7 @@ class MarkdownGenerator {
}
// assign TOC hash
if (count($result) == 2) {
$toc = strtolower($category);
$toc = $category;
}
// add category
array_push(
@@ -480,7 +453,7 @@ class MarkdownGenerator {
);
// add entries
foreach ($entries as $entry) {
$result[] = MarkdownGenerator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $entry);
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $entry);
}
}
}
@@ -502,7 +475,7 @@ class MarkdownGenerator {
array_push(
$result,
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`',
MarkdownGenerator::interpolate('* [`' . $member . '`](##{hash})', $entry)
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
);
// add static and plugin sub-entries
@@ -517,7 +490,7 @@ class MarkdownGenerator {
}
foreach ($entry->{$kind} as $subentry) {
$subentry->member = $member;
$result[] = MarkdownGenerator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
}
}
}
@@ -587,4 +560,4 @@ class MarkdownGenerator {
return trim(preg_replace('/[\t ]+\n/', "\n", join($result, "\n")));
}
}
?>
?>

195
vendor/dojo/LICENSE vendored
View File

@@ -1,195 +0,0 @@
Dojo is available under *either* the terms of the modified BSD license *or* the
Academic Free License version 2.1. As a recipient of Dojo, you may choose which
license to receive this code under (except as noted in per-module LICENSE
files). Some modules may not be the copyright of the Dojo Foundation. These
modules contain explicit declarations of copyright in both the LICENSE files in
the directories in which they reside and in the code itself. No external
contributions are allowed under licenses which are fundamentally incompatible
with the AFL or BSD licenses that Dojo is distributed under.
The text of the AFL and BSD licenses is reproduced below.
-------------------------------------------------------------------------------
The "New" BSD License:
**********************
Copyright (c) 2005-2013, The Dojo Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Dojo Foundation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
The Academic Free License, v. 2.1:
**********************************
This Academic Free License (the "License") applies to any original work of
authorship (the "Original Work") whose owner (the "Licensor") has placed the
following notice immediately following the copyright notice for the Original
Work:
Licensed under the Academic Free License version 2.1
1) Grant of Copyright License. Licensor hereby grants You a world-wide,
royalty-free, non-exclusive, perpetual, sublicenseable license to do the
following:
a) to reproduce the Original Work in copies;
b) to prepare derivative works ("Derivative Works") based upon the Original
Work;
c) to distribute copies of the Original Work and Derivative Works to the
public;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) Grant of Patent License. Licensor hereby grants You a world-wide,
royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
claims owned or controlled by the Licensor that are embodied in the Original
Work as furnished by the Licensor, to make, use, sell and offer for sale the
Original Work and Derivative Works.
3) Grant of Source Code License. The term "Source Code" means the preferred
form of the Original Work for making modifications to it and all available
documentation describing how to modify the Original Work. Licensor hereby
agrees to provide a machine-readable copy of the Source Code of the Original
Work along with each copy of the Original Work that Licensor distributes.
Licensor reserves the right to satisfy this obligation by placing a
machine-readable copy of the Source Code in an information repository
reasonably calculated to permit inexpensive and convenient access by You for as
long as Licensor continues to distribute the Original Work, and by publishing
the address of that information repository in a notice immediately following
the copyright notice that applies to the Original Work.
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
of any contributors to the Original Work, nor any of their trademarks or
service marks, may be used to endorse or promote products derived from this
Original Work without express prior written permission of the Licensor. Nothing
in this License shall be deemed to grant any rights to trademarks, copyrights,
patents, trade secrets or any other intellectual property of Licensor except as
expressly stated herein. No patent license is granted to make, use, sell or
offer to sell embodiments of any patent claims other than the licensed claims
defined in Section 2. No right is granted to the trademarks of Licensor even if
such marks are included in the Original Work. Nothing in this License shall be
interpreted to prohibit Licensor from licensing under different terms from this
License any Original Work that Licensor otherwise would have a right to
license.
5) This section intentionally omitted.
6) Attribution Rights. You must retain, in the Source Code of any Derivative
Works that You create, all copyright, patent or trademark notices from the
Source Code of the Original Work, as well as any notices of licensing and any
descriptive text identified therein as an "Attribution Notice." You must cause
the Source Code for any Derivative Works that You create to carry a prominent
Attribution Notice reasonably calculated to inform recipients that You have
modified the Original Work.
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
the copyright in and to the Original Work and the patent rights granted herein
by Licensor are owned by the Licensor or are sublicensed to You under the terms
of this License with the permission of the contributor(s) of those copyrights
and patent rights. Except as expressly stated in the immediately proceeding
sentence, the Original Work is provided under this License on an "AS IS" BASIS
and WITHOUT WARRANTY, either express or implied, including, without limitation,
the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
license to Original Work is granted hereunder except under this disclaimer.
8) Limitation of Liability. Under no circumstances and under no legal theory,
whether in tort (including negligence), contract, or otherwise, shall the
Licensor be liable to any person for any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License
or the use of the Original Work including, without limitation, damages for loss
of goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses. This limitation of liability shall not
apply to liability for death or personal injury resulting from Licensor's
negligence to the extent applicable law prohibits such limitation. Some
jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
9) Acceptance and Termination. If You distribute copies of the Original Work or
a Derivative Work, You must make a reasonable effort under the circumstances to
obtain the express assent of recipients to the terms of this License. Nothing
else but this License (or another written agreement between Licensor and You)
grants You permission to create Derivative Works based upon the Original Work
or to exercise any of the rights granted in Section 1 herein, and any attempt
to do so except under the terms of this License (or another written agreement
between Licensor and You) is expressly prohibited by U.S. copyright law, the
equivalent laws of other countries, and by international treaty. Therefore, by
exercising any of the rights granted to You in Section 1 herein, You indicate
Your acceptance of this License and all of its terms and conditions.
10) Termination for Patent Action. This License shall terminate automatically
and You may no longer exercise any of the rights granted to You by this License
as of the date You commence an action, including a cross-claim or counterclaim,
against Licensor or any licensee alleging that the Original Work infringes a
patent. This termination provision shall not apply for an action alleging
patent infringement by combinations of the Original Work with other software or
hardware.
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
License may be brought only in the courts of a jurisdiction wherein the
Licensor resides or in which Licensor conducts its primary business, and under
the laws of that jurisdiction excluding its conflict-of-law provisions. The
application of the United Nations Convention on Contracts for the International
Sale of Goods is expressly excluded. Any use of the Original Work outside the
scope of this License or after its termination shall be subject to the
requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
seq., the equivalent laws of other countries, and international treaty. This
section shall survive the termination of this License.
12) Attorneys Fees. In any action to enforce the terms of this License or
seeking damages relating thereto, the prevailing party shall be entitled to
recover its costs and expenses, including, without limitation, reasonable
attorneys' fees and costs incurred in connection with such action, including
any appeal of such action. This section shall survive the termination of this
License.
13) Miscellaneous. This License represents the complete agreement concerning
the subject matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent necessary to
make it enforceable.
14) Definition of "You" in This License. "You" throughout this License, whether
in upper or lower case, means an individual or a legal entity exercising rights
under, and complying with all of the terms of, this License. For legal
entities, "You" includes any entity that controls, is controlled by, or is
under common control with you. For purposes of this definition, "control" means
(i) the power, direct or indirect, to cause the direction or management of such
entity, whether by contract or otherwise, or (ii) ownership of fifty percent
(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
entity.
15) Right to Use. You may use the Original Work in all ways not otherwise
restricted or conditioned by this License or by law, and Licensor promises not
to interfere with or be responsible for such uses by You.
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
Permission is hereby granted to copy and distribute this license without
modification. This license may not be modified without the express written
permission of its copyright owner.

1997
vendor/dojo/dojo.js vendored

File diff suppressed because it is too large Load Diff

417
vendor/jquery/README.md vendored Normal file
View File

@@ -0,0 +1,417 @@
[jQuery](http://jquery.com/) - New Wave JavaScript
==================================================
Contribution Guides
--------------------------------------
In the spirit of open source software development, jQuery always encourages community code contribution. To help you get started and before you jump into writing code, be sure to read these important contribution guidelines thoroughly:
1. [Getting Involved](http://docs.jquery.com/Getting_Involved)
2. [Core Style Guide](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
3. [Tips For Bug Patching](http://docs.jquery.com/Tips_for_jQuery_Bug_Patching)
What you need to build your own jQuery
--------------------------------------
In order to build jQuery, you need to have GNU make 3.8 or later, Node.js/npm latest, and git 1.7 or later.
(Earlier versions might work OK, but are not tested.)
Windows users have two options:
1. Install [msysgit](https://code.google.com/p/msysgit/) (Full installer for official Git),
[GNU make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm), and a
[binary version of Node.js](http://node-js.prcn.co.cc/). Make sure all three packages are installed to the same
location (by default, this is C:\Program Files\Git).
2. Install [Cygwin](http://cygwin.com/) (make sure you install the git, make, and which packages), then either follow
the [Node.js build instructions](https://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29) or install
the [binary version of Node.js](http://node-js.prcn.co.cc/).
Mac OS users should install Xcode (comes on your Mac OS install DVD, or downloadable from
[Apple's Xcode site](http://developer.apple.com/technologies/xcode.html)) and
[Homebrew](http://mxcl.github.com/homebrew/). Once Homebrew is installed, run `brew install git` to install git,
and `brew install node` to install Node.js.
Linux/BSD users should use their appropriate package managers to install make, git, and node, or build from source
if you swing that way. Easy-peasy.
How to build your own jQuery
----------------------------
First, clone a copy of the main jQuery git repo by running:
```bash
git clone git://github.com/jquery/jquery.git
```
Enter the directory and install the Node dependencies:
```bash
cd jquery && npm install
```
Make sure you have `grunt` installed by testing:
```bash
grunt -version
```
Then, to get a complete, minified (w/ Uglify.js), linted (w/ JSHint) version of jQuery, type the following:
```bash
grunt
```
The built version of jQuery will be put in the `dist/` subdirectory.
### Modules (new in 1.8)
Starting in jQuery 1.8, special builds can now be created that optionally exclude or include any of the following modules:
- ajax
- css
- dimensions
- effects
- offset
Before creating a custom build for use in production, be sure to check out the latest stable version:
```bash
git pull; git checkout $(git describe --abbrev=0 --tags)
```
Then, make sure all Node dependencies are installed and all Git submodules are checked out:
```bash
npm install && grunt
```
To create a custom build, use the following special `grunt` commands:
Exclude **ajax**:
```bash
grunt custom:-ajax
```
Exclude **css**:
```bash
grunt custom:-css
```
Exclude **deprecated**:
```bash
grunt custom:-deprecated
```
Exclude **dimensions**:
```bash
grunt custom:-dimensions
```
Exclude **effects**:
```bash
grunt custom:-effects
```
Exclude **offset**:
```bash
grunt custom:-offset
```
Exclude **all** optional modules:
```bash
grunt custom:-ajax,-css,-deprecated,-dimensions,-effects,-offset
```
Note: dependencies will be handled internally, by the build process.
Running the Unit Tests
--------------------------------------
Start grunt to auto-build jQuery as you work:
```bash
cd jquery && grunt watch
```
Run the unit tests with a local server that supports PHP. No database is required. Pre-configured php local servers are available for Windows and Mac. Here are some options:
- Windows: [WAMP download](http://www.wampserver.com/en/)
- Mac: [MAMP download](http://www.mamp.info/en/index.html)
- Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation)
- [Mongoose (most platforms)](http://code.google.com/p/mongoose/)
Building to a different directory
---------------------------------
If you want to build jQuery to a directory that is different from the default location:
```bash
grunt && grunt dist:/path/to/special/location/
```
With this example, the output files would be:
```bash
/path/to/special/location/jquery.js
/path/to/special/location/jquery.min.js
```
If you want to add a permanent copy destination, create a file in `dist/` called ".destination.json". Inside the file, paste and customize the following:
```json
{
"/Absolute/path/to/other/destination": true
}
```
Additionally, both methods can be combined.
Updating Submodules
-------------------
Update the submodules to what is probably the latest upstream code.
```bash
grunt update_submodules
```
Note: This task will also be run any time the default `grunt` command is used.
Git for dummies
---------------
As the source code is handled by the version control system Git, it's useful to know some features used.
### Submodules ###
The repository uses submodules, which normally are handled directly by the Makefile, but sometimes you want to
be able to work with them manually.
Following are the steps to manually get the submodules:
```bash
git clone https://github.com/jquery/jquery.git
cd jquery
git submodule init
git submodule update
```
Or:
```bash
git clone https://github.com/jquery/jquery.git
cd jquery
git submodule update --init
```
Or:
```bash
git clone --recursive https://github.com/jquery/jquery.git
cd jquery
```
If you want to work inside a submodule, it is possible, but first you need to checkout a branch:
```bash
cd src/sizzle
git checkout master
```
After you've committed your changes to the submodule, you'll update the jquery project to point to the new commit,
but remember to push the submodule changes before pushing the new jquery commit:
```bash
cd src/sizzle
git push origin master
cd ..
git add src/sizzle
git commit
```
### cleaning ###
If you want to purge your working directory back to the status of upstream, following commands can be used (remember everything you've worked on is gone after these):
```bash
git reset --hard upstream/master
git clean -fdx
```
### rebasing ###
For feature/topic branches, you should always used the `--rebase` flag to `git pull`, or if you are usually handling many temporary "to be in a github pull request" branches, run following to automate this:
```bash
git config branch.autosetuprebase local
```
(see `man git-config` for more information)
### handling merge conflicts ###
If you're getting merge conflicts when merging, instead of editing the conflicted files manually, you can use the feature
`git mergetool`. Even though the default tool `xxdiff` looks awful/old, it's rather useful.
Following are some commands that can be used there:
* `Ctrl + Alt + M` - automerge as much as possible
* `b` - jump to next merge conflict
* `s` - change the order of the conflicted lines
* `u` - undo an merge
* `left mouse button` - mark a block to be the winner
* `middle mouse button` - mark a line to be the winner
* `Ctrl + S` - save
* `Ctrl + Q` - quit
[QUnit](http://docs.jquery.com/QUnit) Reference
-----------------
### Test methods ###
```js
expect( numAssertions );
stop();
start();
```
note: QUnit's eventual addition of an argument to stop/start is ignored in this test suite so that start and stop can be passed as callbacks without worrying about their parameters
### Test assertions ###
```js
ok( value, [message] );
equal( actual, expected, [message] );
notEqual( actual, expected, [message] );
deepEqual( actual, expected, [message] );
notDeepEqual( actual, expected, [message] );
strictEqual( actual, expected, [message] );
notStrictEqual( actual, expected, [message] );
raises( block, [expected], [message] );
```
Test Suite Convenience Methods Reference (See [test/data/testinit.js](https://github.com/jquery/jquery/blob/master/test/data/testinit.js))
------------------------------
### Returns an array of elements with the given IDs ###
```js
q( ... );
```
Example:
```js
q("main", "foo", "bar");
=> [ div#main, span#foo, input#bar ]
```
### Asserts that a selection matches the given IDs ###
```js
t( testName, selector, [ "array", "of", "ids" ] );
```
Example:
```js
t("Check for something", "//[a]", ["foo", "baar"]);
```
### Fires a native DOM event without going through jQuery ###
```js
fireNative( node, eventType )
```
Example:
```js
fireNative( jQuery("#elem")[0], "click" );
```
### Add random number to url to stop caching ###
```js
url( "some/url.php" );
```
Example:
```js
url("data/test.html");
=> "data/test.html?10538358428943"
url("data/test.php?foo=bar");
=> "data/test.php?foo=bar&10538358345554"
```
### Load tests in an iframe ###
Loads a given page constructing a url with fileName: `"./data/" + fileName + ".html"`
and fires the given callback on jQuery ready (using the jQuery loading from that page)
and passes the iFrame's jQuery to the callback.
```js
testIframe( fileName, testName, callback );
```
Callback arguments:
```js
callback( jQueryFromIFrame, iFrameWindow, iFrameDocument );
```
### Load tests in an iframe (window.iframeCallback) ###
Loads a given page constructing a url with fileName: `"./data/" + fileName + ".html"`
The given callback is fired when window.iframeCallback is called by the page
The arguments passed to the callback are the same as the
arguments passed to window.iframeCallback, whatever that may be
```js
testIframeWithCallback( testName, fileName, callback );
```
Questions?
----------
If you have any questions, please feel free to ask on the
[Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.

View File

@@ -1,486 +0,0 @@
/*
json2.js
2013-05-26
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function () {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

20
vendor/json3/LICENSE vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2012 Kit Cambridge.
http://kitcambridge.github.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.

124
vendor/json3/README.md vendored Normal file
View File

@@ -0,0 +1,124 @@
# JSON 3 #
![JSON 3 Logo](http://bestiejs.github.com/json3/page/logo.png)
**JSON 3** is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is **3.2.4**.
- [Development Version](http://cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.js) *(36.5 KB; uncompressed with comments)*
- [Production Version](http://cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.min.js) *(3.0 KB; compressed and `gzip`-ped)*
[JSON](http://json.org/) is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by [Douglas Crockford](http://www.crockford.com/), the format was standardized in the [fifth edition](http://es5.github.com/) of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.
JSON 3 exposes two functions: `stringify()` for [serializing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify) a JavaScript value to JSON, and `parse()` for [producing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse) a JavaScript value from a JSON source string. It is a **drop-in replacement** for [JSON 2](http://json.org/js). The functions behave exactly as described in the ECMAScript spec, **except** for the date serialization discrepancy noted below.
The JSON 3 parser does **not** use `eval` or regular expressions. This provides security and performance benefits in obsolete and mobile environments, where the margin is particularly significant. The complete [benchmark suite](http://jsperf.com/json3) is available on [jsPerf](http://jsperf.com/).
The project is [hosted on GitHub](http://git.io/json3), along with the [unit tests](http://bestiejs.github.com/json3/test/test_browser.html). It is part of the [BestieJS](https://github.com/bestiejs) family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.
# Changes from JSON 2 #
JSON 3...
* Correctly serializes primitive wrapper objects.
* Throws a `TypeError` when serializing cyclic structures (JSON 2 recurses until the call stack overflows).
* Utilizes **feature tests** to detect broken or incomplete *native* JSON implementations (JSON 2 only checks for the presence of the native functions). The tests are only executed once at runtime, so there is no additional performance cost when parsing or serializing values.
**As of v3.2.3**, JSON 3 is compatible with [Prototype](http://prototypejs.org) 1.6.1 and older.
In contrast to JSON 2, JSON 3 **does not**...
* Add `toJSON()` methods to the `Boolean`, `Number`, and `String` prototypes. These are not part of any standard, and are made redundant by the design of the `stringify()` implementation.
* Add `toJSON()` or `toISOString()` methods to `Date.prototype`. See the note about date serialization below.
## Date Serialization
**JSON 3 deviates from the specification in one important way**: it does not define `Date#toISOString()` or `Date#toJSON()`. This preserves CommonJS compatibility and avoids polluting native prototypes. Instead, date serialization is performed internally by the `stringify()` implementation: if a date object does not define a custom `toJSON()` method, it is serialized as a [simplified ISO 8601 date-time string](http://es5.github.com/#x15.9.1.15).
**Several native `Date#toJSON()` implementations produce date time strings that do *not* conform to the grammar outlined in the spec**. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string `"Invalid Date"`, rather than `null`. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native `stringify()` implementation.
Portions of the date serialization code are adapted from the [`date-shim`](https://github.com/Yaffle/date-shim) project.
# Usage #
## Web Browsers
<script src="//cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.min.js"></script>
<script>
JSON.stringify({"Hello": 123});
// => '{"Hello":123}'
JSON.parse("[[1, 2, 3], 1, 2, 3, 4]", function (key, value) {
if (typeof value == "number") {
value = value % 2 ? "Odd" : "Even";
}
return value;
});
// => [["Odd", "Even", "Odd"], "Odd", "Even", "Odd", "Even"]
</script>
## CommonJS Environments
var JSON3 = require("./path/to/json3");
JSON3.parse("[1, 2, 3]");
// => [1, 2, 3]
## JavaScript Engines
load("path/to/json3.js");
JSON.stringify({"Hello": 123, "Good-bye": 456}, ["Hello"], "\t");
// => '{\n\t"Hello": 123\n}'
# Compatibility #
JSON 3 has been **tested** with the following web browsers, CommonJS environments, and JavaScript engines.
## Web Browsers
- Windows [Internet Explorer](http://www.microsoft.com/windows/internet-explorer), version 6.0 and higher
- Mozilla [Firefox](http://www.mozilla.com/firefox), version 1.0 and higher
- Apple [Safari](http://www.apple.com/safari), version 2.0 and higher
- [Opera](http://www.opera.com) 7.02 and higher
- [Mozilla](http://sillydog.org/narchive/gecko.php) 1.0, [Netscape](http://sillydog.org/narchive/) 6.2.3, and [SeaMonkey](http://www.seamonkey-project.org/) 1.0 and higher
## CommonJS Environments
- [Node](http://nodejs.org/) 0.2.6 and higher
- [RingoJS](http://ringojs.org/) 0.4 and higher
- [Narwhal](http://narwhaljs.org/) 0.3.2 and higher
## JavaScript Engines
- Mozilla [Rhino](http://www.mozilla.org/rhino) 1.5R5 and higher
- WebKit [JSC](https://trac.webkit.org/wiki/JSC)
- Google [V8](http://code.google.com/p/v8)
## Known Incompatibilities
* Attempting to serialize the `arguments` object may produce inconsistent results across environments due to specification version differences. As a workaround, please convert the `arguments` object to an array first: `JSON.stringify([].slice.call(arguments, 0))`.
## Required Native Methods
JSON 3 assumes that the following methods exist and function as described in the ECMAScript specification:
- The `Number`, `String`, `Array`, `Object`, `Date`, `SyntaxError`, and `TypeError` constructors.
- `String.fromCharCode`
- `Object#toString`
- `Function#call`
- `Math.floor`
- `Number#toString`
- `Date#valueOf`
- `String.prototype`: `indexOf`, `charCodeAt`, `charAt`, `slice`.
- `Array.prototype`: `push`, `pop`, `join`.
# Contribute #
Check out a working copy of the JSON 3 source code with [Git](http://git-scm.com/):
$ git clone git://github.com/bestiejs/json3.git
$ cd json3
$ git submodule update --init
If you'd like to contribute a feature or bug fix, you can [fork](http://help.github.com/fork-a-repo/) JSON 3, commit your changes, and [send a pull request](http://help.github.com/send-pull-requests/). Please make sure to update the unit tests in the `test` directory as well.
Alternatively, you can use the [GitHub issue tracker](https://github.com/bestiejs/json3/issues) to submit bug reports, feature requests, and questions, or send tweets to [@kitcambridge](http://twitter.com/kitcambridge).
JSON 3 is released under the [MIT License](http://kit.mit-license.org/).

783
vendor/json3/lib/json3.js vendored Normal file
View File

@@ -0,0 +1,783 @@
/*! JSON v3.2.4 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
;(function () {
// Convenience aliases.
var getClass = {}.toString, isProperty, forEach, undef;
// Detect the `define` function exposed by asynchronous module loaders. The
// strict `define` check is necessary for compatibility with `r.js`.
var isLoader = typeof define === "function" && define.amd, JSON3 = !isLoader && typeof exports == "object" && exports;
if (JSON3 || isLoader) {
if (typeof JSON == "object" && JSON) {
// Delegate to the native `stringify` and `parse` implementations in
// asynchronous module loaders and CommonJS environments.
if (isLoader) {
JSON3 = JSON;
} else {
JSON3.stringify = JSON.stringify;
JSON3.parse = JSON.parse;
}
} else if (isLoader) {
JSON3 = this.JSON = {};
}
} else {
// Export for web browsers and JavaScript engines.
JSON3 = this.JSON || (this.JSON = {});
}
// Local variables.
var Escapes, toPaddedString, quote, serialize;
var fromCharCode, Unescapes, abort, lex, get, walk, update, Index, Source;
// Test the `Date#getUTC*` methods. Based on work by @Yaffle.
var isExtended = new Date(-3509827334573292), floor, Months, getDay;
try {
// The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
// results for certain dates in Opera >= 10.53.
isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() == 1 &&
// Safari < 2.0.2 stores the internal millisecond time value correctly,
// but clips the values returned by the date methods to the range of
// signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
} catch (exception) {}
// Internal: Determines whether the native `JSON.stringify` and `parse`
// implementations are spec-compliant. Based on work by Ken Snyder.
function has(name) {
var stringifySupported, parseSupported, value, serialized = '{"A":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}', all = name == "json";
if (all || name == "json-stringify" || name == "json-parse") {
// Test `JSON.stringify`.
if (name == "json-stringify" || all) {
if ((stringifySupported = typeof JSON3.stringify == "function" && isExtended)) {
// A test function object with a custom `toJSON` method.
(value = function () {
return 1;
}).toJSON = value;
try {
stringifySupported =
// Firefox 3.1b1 and b2 serialize string, number, and boolean
// primitives as object literals.
JSON3.stringify(0) === "0" &&
// FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
// literals.
JSON3.stringify(new Number()) === "0" &&
JSON3.stringify(new String()) == '""' &&
// FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
// does not define a canonical JSON representation (this applies to
// objects with `toJSON` properties as well, *unless* they are nested
// within an object or array).
JSON3.stringify(getClass) === undef &&
// IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
// FF 3.1b3 pass this test.
JSON3.stringify(undef) === undef &&
// Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
// respectively, if the value is omitted entirely.
JSON3.stringify() === undef &&
// FF 3.1b1, 2 throw an error if the given value is not a number,
// string, array, object, Boolean, or `null` literal. This applies to
// objects with custom `toJSON` methods as well, unless they are nested
// inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
// methods entirely.
JSON3.stringify(value) === "1" &&
JSON3.stringify([value]) == "[1]" &&
// Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
// `"[null]"`.
JSON3.stringify([undef]) == "[null]" &&
// YUI 3.0.0b1 fails to serialize `null` literals.
JSON3.stringify(null) == "null" &&
// FF 3.1b1, 2 halts serialization if an array contains a function:
// `[1, true, getClass, 1]` serializes as "[1,true,],". These versions
// of Firefox also allow trailing commas in JSON objects and arrays.
// FF 3.1b3 elides non-JSON values from objects and arrays, unless they
// define custom `toJSON` methods.
JSON3.stringify([undef, getClass, null]) == "[null,null,null]" &&
// Simple serialization test. FF 3.1b1 uses Unicode escape sequences
// where character escape codes are expected (e.g., `\b` => `\u0008`).
JSON3.stringify({ "A": [value, true, false, null, "\0\b\n\f\r\t"] }) == serialized &&
// FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
JSON3.stringify(null, value) === "1" &&
JSON3.stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
// JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
// serialize extended years.
JSON3.stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
// The milliseconds are optional in ES 5, but required in 5.1.
JSON3.stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
// Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
// four-digit years instead of six-digit years. Credits: @Yaffle.
JSON3.stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
// Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
// values less than 1000. Credits: @Yaffle.
JSON3.stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
} catch (exception) {
stringifySupported = false;
}
}
if (!all) {
return stringifySupported;
}
}
// Test `JSON.parse`.
if (name == "json-parse" || all) {
if (typeof JSON3.parse == "function") {
try {
// FF 3.1b1, b2 will throw an exception if a bare literal is provided.
// Conforming implementations should also coerce the initial argument to
// a string prior to parsing.
if (JSON3.parse("0") === 0 && !JSON3.parse(false)) {
// Simple parsing test.
value = JSON3.parse(serialized);
if ((parseSupported = value.A.length == 5 && value.A[0] == 1)) {
try {
// Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
parseSupported = !JSON3.parse('"\t"');
} catch (exception) {}
if (parseSupported) {
try {
// FF 4.0 and 4.0.1 allow leading `+` signs, and leading and
// trailing decimal points. FF 4.0, 4.0.1, and IE 9-10 also
// allow certain octal literals.
parseSupported = JSON3.parse("01") != 1;
} catch (exception) {}
}
}
}
} catch (exception) {
parseSupported = false;
}
}
if (!all) {
return parseSupported;
}
}
return stringifySupported && parseSupported;
}
}
if (!has("json")) {
// Define additional utility methods if the `Date` methods are buggy.
if (!isExtended) {
floor = Math.floor;
// A mapping between the months of the year and the number of days between
// January 1st and the first of the respective month.
Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
// Internal: Calculates the number of days between the Unix epoch and the
// first day of the given month.
getDay = function (year, month) {
return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
};
}
// Internal: Determines if a property is a direct property of the given
// object. Delegates to the native `Object#hasOwnProperty` method.
if (!(isProperty = {}.hasOwnProperty)) {
isProperty = function (property) {
var members = {}, constructor;
if ((members.__proto__ = null, members.__proto__ = {
// The *proto* property cannot be set multiple times in recent
// versions of Firefox and SeaMonkey.
"toString": 1
}, members).toString != getClass) {
// Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
// supports the mutable *proto* property.
isProperty = function (property) {
// Capture and break the object's prototype chain (see section 8.6.2
// of the ES 5.1 spec). The parenthesized expression prevents an
// unsafe transformation by the Closure Compiler.
var original = this.__proto__, result = property in (this.__proto__ = null, this);
// Restore the original prototype chain.
this.__proto__ = original;
return result;
};
} else {
// Capture a reference to the top-level `Object` constructor.
constructor = members.constructor;
// Use the `constructor` property to simulate `Object#hasOwnProperty` in
// other environments.
isProperty = function (property) {
var parent = (this.constructor || constructor).prototype;
return property in this && !(property in parent && this[property] === parent[property]);
};
}
members = null;
return isProperty.call(this, property);
};
}
// Internal: Normalizes the `for...in` iteration algorithm across
// environments. Each enumerated key is yielded to a `callback` function.
forEach = function (object, callback) {
var size = 0, Properties, members, property, forEach;
// Tests for bugs in the current environment's `for...in` algorithm. The
// `valueOf` property inherits the non-enumerable flag from
// `Object.prototype` in older versions of IE, Netscape, and Mozilla.
(Properties = function () {
this.valueOf = 0;
}).prototype.valueOf = 0;
// Iterate over a new instance of the `Properties` class.
members = new Properties();
for (property in members) {
// Ignore all properties inherited from `Object.prototype`.
if (isProperty.call(members, property)) {
size++;
}
}
Properties = members = null;
// Normalize the iteration algorithm.
if (!size) {
// A list of non-enumerable properties inherited from `Object.prototype`.
members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
// IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
// properties.
forEach = function (object, callback) {
var isFunction = getClass.call(object) == "[object Function]", property, length;
for (property in object) {
// Gecko <= 1.0 enumerates the `prototype` property of functions under
// certain conditions; IE does not.
if (!(isFunction && property == "prototype") && isProperty.call(object, property)) {
callback(property);
}
}
// Manually invoke the callback for each non-enumerable property.
for (length = members.length; property = members[--length]; isProperty.call(object, property) && callback(property));
};
} else if (size == 2) {
// Safari <= 2.0.4 enumerates shadowed properties twice.
forEach = function (object, callback) {
// Create a set of iterated properties.
var members = {}, isFunction = getClass.call(object) == "[object Function]", property;
for (property in object) {
// Store each property name to prevent double enumeration. The
// `prototype` property of functions is not enumerated due to cross-
// environment inconsistencies.
if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
callback(property);
}
}
};
} else {
// No bugs detected; use the standard `for...in` algorithm.
forEach = function (object, callback) {
var isFunction = getClass.call(object) == "[object Function]", property, isConstructor;
for (property in object) {
if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
callback(property);
}
}
// Manually invoke the callback for the `constructor` property due to
// cross-environment inconsistencies.
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
callback(property);
}
};
}
return forEach(object, callback);
};
// Public: Serializes a JavaScript `value` as a JSON string. The optional
// `filter` argument may specify either a function that alters how object and
// array members are serialized, or an array of strings and numbers that
// indicates which properties should be serialized. The optional `width`
// argument may be either a string or number that specifies the indentation
// level of the output.
if (!has("json-stringify")) {
// Internal: A map of control characters and their escaped equivalents.
Escapes = {
"\\": "\\\\",
'"': '\\"',
"\b": "\\b",
"\f": "\\f",
"\n": "\\n",
"\r": "\\r",
"\t": "\\t"
};
// Internal: Converts `value` into a zero-padded string such that its
// length is at least equal to `width`. The `width` must be <= 6.
toPaddedString = function (width, value) {
// The `|| 0` expression is necessary to work around a bug in
// Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
return ("000000" + (value || 0)).slice(-width);
};
// Internal: Double-quotes a string `value`, replacing all ASCII control
// characters (characters with code unit values between 0 and 31) with
// their escaped equivalents. This is an implementation of the
// `Quote(value)` operation defined in ES 5.1 section 15.12.3.
quote = function (value) {
var result = '"', index = 0, symbol;
for (; symbol = value.charAt(index); index++) {
// Escape the reverse solidus, double quote, backspace, form feed, line
// feed, carriage return, and tab characters.
result += '\\"\b\f\n\r\t'.indexOf(symbol) > -1 ? Escapes[symbol] :
// If the character is a control character, append its Unicode escape
// sequence; otherwise, append the character as-is.
(Escapes[symbol] = symbol < " " ? "\\u00" + toPaddedString(2, symbol.charCodeAt(0).toString(16)) : symbol);
}
return result + '"';
};
// Internal: Recursively serializes an object. Implements the
// `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
var value = object[property], className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, any, result;
if (typeof value == "object" && value) {
className = getClass.call(value);
if (className == "[object Date]" && !isProperty.call(value, "toJSON")) {
if (value > -1 / 0 && value < 1 / 0) {
// Dates are serialized according to the `Date#toJSON` method
// specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
// for the ISO 8601 date time string format.
if (getDay) {
// Manually compute the year, month, date, hours, minutes,
// seconds, and milliseconds if the `getUTC*` methods are
// buggy. Adapted from @Yaffle's `date-shim` project.
date = floor(value / 864e5);
for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
date = 1 + date - getDay(year, month);
// The `time` value specifies the time within the day (see ES
// 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
// to compute `A modulo B`, as the `%` operator does not
// correspond to the `modulo` operation for negative numbers.
time = (value % 864e5 + 864e5) % 864e5;
// The hours, minutes, seconds, and milliseconds are obtained by
// decomposing the time within the day. See section 15.9.1.10.
hours = floor(time / 36e5) % 24;
minutes = floor(time / 6e4) % 60;
seconds = floor(time / 1e3) % 60;
milliseconds = time % 1e3;
} else {
year = value.getUTCFullYear();
month = value.getUTCMonth();
date = value.getUTCDate();
hours = value.getUTCHours();
minutes = value.getUTCMinutes();
seconds = value.getUTCSeconds();
milliseconds = value.getUTCMilliseconds();
}
// Serialize extended years correctly.
value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
"-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
// Months, dates, hours, minutes, and seconds should have two
// digits; milliseconds should have three.
"T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
// Milliseconds are optional in ES 5.0, but required in 5.1.
"." + toPaddedString(3, milliseconds) + "Z";
} else {
value = null;
}
} else if (typeof value.toJSON == "function" && ((className != "[object Number]" && className != "[object String]" && className != "[object Array]") || isProperty.call(value, "toJSON"))) {
// Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
// `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
// ignores all `toJSON` methods on these objects unless they are
// defined directly on an instance.
value = value.toJSON(property);
}
}
if (callback) {
// If a replacement function was provided, call it to obtain the value
// for serialization.
value = callback.call(object, property, value);
}
if (value === null) {
return "null";
}
className = getClass.call(value);
if (className == "[object Boolean]") {
// Booleans are represented literally.
return "" + value;
} else if (className == "[object Number]") {
// JSON numbers must be finite. `Infinity` and `NaN` are serialized as
// `"null"`.
return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
} else if (className == "[object String]") {
// Strings are double-quoted and escaped.
return quote(value);
}
// Recursively serialize objects and arrays.
if (typeof value == "object") {
// Check for cyclic structures. This is a linear search; performance
// is inversely proportional to the number of unique nested objects.
for (length = stack.length; length--;) {
if (stack[length] === value) {
// Cyclic structures cannot be serialized by `JSON.stringify`.
throw TypeError();
}
}
// Add the object to the stack of traversed objects.
stack.push(value);
results = [];
// Save the current indentation level and indent one additional level.
prefix = indentation;
indentation += whitespace;
if (className == "[object Array]") {
// Recursively serialize array elements.
for (index = 0, length = value.length; index < length; any || (any = true), index++) {
element = serialize(index, value, callback, properties, whitespace, indentation, stack);
results.push(element === undef ? "null" : element);
}
result = any ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
} else {
// Recursively serialize object members. Members are selected from
// either a user-specified list of property names, or the object
// itself.
forEach(properties || value, function (property) {
var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
if (element !== undef) {
// According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
// is not the empty string, let `member` {quote(property) + ":"}
// be the concatenation of `member` and the `space` character."
// The "`space` character" refers to the literal space
// character, not the `space` {width} argument provided to
// `JSON.stringify`.
results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
}
any || (any = true);
});
result = any ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
}
// Remove the object from the traversed object stack.
stack.pop();
return result;
}
};
// Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
JSON3.stringify = function (source, filter, width) {
var whitespace, callback, properties, index, length, value;
if (typeof filter == "function" || typeof filter == "object" && filter) {
if (getClass.call(filter) == "[object Function]") {
callback = filter;
} else if (getClass.call(filter) == "[object Array]") {
// Convert the property names array into a makeshift set.
properties = {};
for (index = 0, length = filter.length; index < length; value = filter[index++], ((getClass.call(value) == "[object String]" || getClass.call(value) == "[object Number]") && (properties[value] = 1)));
}
}
if (width) {
if (getClass.call(width) == "[object Number]") {
// Convert the `width` to an integer and create a string containing
// `width` number of space characters.
if ((width -= width % 1) > 0) {
for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
}
} else if (getClass.call(width) == "[object String]") {
whitespace = width.length <= 10 ? width : width.slice(0, 10);
}
}
// Opera <= 7.54u2 discards the values associated with empty string keys
// (`""`) only if they are used directly within an object member list
// (e.g., `!("" in { "": 1})`).
return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
};
}
// Public: Parses a JSON source string.
if (!has("json-parse")) {
fromCharCode = String.fromCharCode;
// Internal: A map of escaped control characters and their unescaped
// equivalents.
Unescapes = {
"\\": "\\",
'"': '"',
"/": "/",
"b": "\b",
"t": "\t",
"n": "\n",
"f": "\f",
"r": "\r"
};
// Internal: Resets the parser state and throws a `SyntaxError`.
abort = function() {
Index = Source = null;
throw SyntaxError();
};
// Internal: Returns the next token, or `"$"` if the parser has reached
// the end of the source string. A token may be a string, number, `null`
// literal, or Boolean literal.
lex = function () {
var source = Source, length = source.length, symbol, value, begin, position, sign;
while (Index < length) {
symbol = source.charAt(Index);
if ("\t\r\n ".indexOf(symbol) > -1) {
// Skip whitespace tokens, including tabs, carriage returns, line
// feeds, and space characters.
Index++;
} else if ("{}[]:,".indexOf(symbol) > -1) {
// Parse a punctuator token at the current position.
Index++;
return symbol;
} else if (symbol == '"') {
// Advance to the next character and parse a JSON string at the
// current position. String tokens are prefixed with the sentinel
// `@` character to distinguish them from punctuators.
for (value = "@", Index++; Index < length;) {
symbol = source.charAt(Index);
if (symbol < " ") {
// Unescaped ASCII control characters are not permitted.
abort();
} else if (symbol == "\\") {
// Parse escaped JSON control characters, `"`, `\`, `/`, and
// Unicode escape sequences.
symbol = source.charAt(++Index);
if ('\\"/btnfr'.indexOf(symbol) > -1) {
// Revive escaped control characters.
value += Unescapes[symbol];
Index++;
} else if (symbol == "u") {
// Advance to the first character of the escape sequence.
begin = ++Index;
// Validate the Unicode escape sequence.
for (position = Index + 4; Index < position; Index++) {
symbol = source.charAt(Index);
// A valid sequence comprises four hexdigits that form a
// single hexadecimal value.
if (!(symbol >= "0" && symbol <= "9" || symbol >= "a" && symbol <= "f" || symbol >= "A" && symbol <= "F")) {
// Invalid Unicode escape sequence.
abort();
}
}
// Revive the escaped character.
value += fromCharCode("0x" + source.slice(begin, Index));
} else {
// Invalid escape sequence.
abort();
}
} else {
if (symbol == '"') {
// An unescaped double-quote character marks the end of the
// string.
break;
}
// Append the original character as-is.
value += symbol;
Index++;
}
}
if (source.charAt(Index) == '"') {
Index++;
// Return the revived string.
return value;
}
// Unterminated string.
abort();
} else {
// Parse numbers and literals.
begin = Index;
// Advance the scanner's position past the sign, if one is
// specified.
if (symbol == "-") {
sign = true;
symbol = source.charAt(++Index);
}
// Parse an integer or floating-point value.
if (symbol >= "0" && symbol <= "9") {
// Leading zeroes are interpreted as octal literals.
if (symbol == "0" && (symbol = source.charAt(Index + 1), symbol >= "0" && symbol <= "9")) {
// Illegal octal literal.
abort();
}
sign = false;
// Parse the integer component.
for (; Index < length && (symbol = source.charAt(Index), symbol >= "0" && symbol <= "9"); Index++);
// Floats cannot contain a leading decimal point; however, this
// case is already accounted for by the parser.
if (source.charAt(Index) == ".") {
position = ++Index;
// Parse the decimal component.
for (; position < length && (symbol = source.charAt(position), symbol >= "0" && symbol <= "9"); position++);
if (position == Index) {
// Illegal trailing decimal.
abort();
}
Index = position;
}
// Parse exponents.
symbol = source.charAt(Index);
if (symbol == "e" || symbol == "E") {
// Skip past the sign following the exponent, if one is
// specified.
symbol = source.charAt(++Index);
if (symbol == "+" || symbol == "-") {
Index++;
}
// Parse the exponential component.
for (position = Index; position < length && (symbol = source.charAt(position), symbol >= "0" && symbol <= "9"); position++);
if (position == Index) {
// Illegal empty exponent.
abort();
}
Index = position;
}
// Coerce the parsed value to a JavaScript number.
return +source.slice(begin, Index);
}
// A negative sign may only precede numbers.
if (sign) {
abort();
}
// `true`, `false`, and `null` literals.
if (source.slice(Index, Index + 4) == "true") {
Index += 4;
return true;
} else if (source.slice(Index, Index + 5) == "false") {
Index += 5;
return false;
} else if (source.slice(Index, Index + 4) == "null") {
Index += 4;
return null;
}
// Unrecognized token.
abort();
}
}
// Return the sentinel `$` character if the parser has reached the end
// of the source string.
return "$";
};
// Internal: Parses a JSON `value` token.
get = function (value) {
var results, any, key;
if (value == "$") {
// Unexpected end of input.
abort();
}
if (typeof value == "string") {
if (value.charAt(0) == "@") {
// Remove the sentinel `@` character.
return value.slice(1);
}
// Parse object and array literals.
if (value == "[") {
// Parses a JSON array, returning a new JavaScript array.
results = [];
for (;; any || (any = true)) {
value = lex();
// A closing square bracket marks the end of the array literal.
if (value == "]") {
break;
}
// If the array literal contains elements, the current token
// should be a comma separating the previous element from the
// next.
if (any) {
if (value == ",") {
value = lex();
if (value == "]") {
// Unexpected trailing `,` in array literal.
abort();
}
} else {
// A `,` must separate each array element.
abort();
}
}
// Elisions and leading commas are not permitted.
if (value == ",") {
abort();
}
results.push(get(value));
}
return results;
} else if (value == "{") {
// Parses a JSON object, returning a new JavaScript object.
results = {};
for (;; any || (any = true)) {
value = lex();
// A closing curly brace marks the end of the object literal.
if (value == "}") {
break;
}
// If the object literal contains members, the current token
// should be a comma separator.
if (any) {
if (value == ",") {
value = lex();
if (value == "}") {
// Unexpected trailing `,` in object literal.
abort();
}
} else {
// A `,` must separate each object member.
abort();
}
}
// Leading commas are not permitted, object property names must be
// double-quoted strings, and a `:` must separate each property
// name and value.
if (value == "," || typeof value != "string" || value.charAt(0) != "@" || lex() != ":") {
abort();
}
results[value.slice(1)] = get(lex());
}
return results;
}
// Unexpected token encountered.
abort();
}
return value;
};
// Internal: Updates a traversed object member.
update = function(source, property, callback) {
var element = walk(source, property, callback);
if (element === undef) {
delete source[property];
} else {
source[property] = element;
}
};
// Internal: Recursively traverses a parsed JSON object, invoking the
// `callback` function for each value. This is an implementation of the
// `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
walk = function (source, property, callback) {
var value = source[property], length;
if (typeof value == "object" && value) {
if (getClass.call(value) == "[object Array]") {
for (length = value.length; length--;) {
update(value, length, callback);
}
} else {
// `forEach` can't be used to traverse an array in Opera <= 8.54,
// as `Object#hasOwnProperty` returns `false` for array indices
// (e.g., `![1, 2, 3].hasOwnProperty("0")`).
forEach(value, function (property) {
update(value, property, callback);
});
}
}
return callback.call(source, property, value);
};
// Public: `JSON.parse`. See ES 5.1 section 15.12.2.
JSON3.parse = function (source, callback) {
var result, value;
Index = 0;
Source = source;
result = get(lex());
// If a JSON string contains multiple tokens, it is invalid.
if (lex() != "$") {
abort();
}
// Reset the parser state.
Index = Source = null;
return callback && getClass.call(callback) == "[object Function]" ? walk((value = {}, value[""] = result, value), "", callback) : result;
};
}
}
// Export for asynchronous module loaders.
if (isLoader) {
define(function () {
return JSON3;
});
}
}).call(this);

100
vendor/platform.js/README.md vendored Normal file
View File

@@ -0,0 +1,100 @@
# Platform.js <sup>v1.0.0</sup>
A platform detection library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>.
## Disclaimer
Platform.js is for informational purposes only and **not** intended as a substitution for [feature detection/inference](http://allyoucanleet.com/post/18087210413/feature-testing-costs#screencast2) checks.
## BestieJS
Platform.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Documentation
The documentation for Platform.js can be viewed here: [/doc/README.md](https://github.com/bestiejs/platform.js/blob/master/doc/README.md#readme)
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap).
## Support
Platform.js has been tested in at least Chrome 5~27, Firefox 2~21, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.10.7, Narwhal 0.3.2, PhantomJS 1.9.0, RingoJS 0.9, and Rhino 1.7RC5.
## Installation and usage
In a browser or Adobe AIR:
```html
<script src="platform.js"></script>
```
Via [npm](http://npmjs.org/):
```bash
npm install platform
```
In [Node.js](http://nodejs.org/) and [RingoJS](http://ringojs.org/):
```js
var platform = require('platform');
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('platform.js');
```
In an AMD loader like [RequireJS](http://requirejs.org/):
```js
require({
'paths': {
'platform': 'path/to/platform'
}
},
['platform'], function(platform) {
console.log(platform.name);
});
```
Usage example:
```js
// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition
platform.name; // 'IE'
platform.version; // '10.0'
platform.layout; // 'Trident'
platform.os; // 'Windows Server 2008 R2 / 7 x64'
platform.description; // 'IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64'
// or on an iPad
platform.name; // 'Safari'
platform.version; // '5.1'
platform.product; // 'iPad'
platform.manufacturer; // 'Apple'
platform.layout; // 'WebKit'
platform.os; // 'iOS 5.0'
platform.description; // 'Safari 5.1 on Apple iPad (iOS 5.0)'
// or parsing a given UA string
var info = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 11.52');
info.name; // 'Opera'
info.version; // '11.52'
info.layout; // 'Presto'
info.os; // 'Mac OS X 10.7.2'
info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2'
```
## Author
| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
|---|
| [John-David Dalton](http://allyoucanleet.com/) |
## Contributors
| [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](http://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](http://mathiasbynens.be/) |

View File

@@ -3,18 +3,18 @@
* Copyright 2010-2013 John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit>
*/
;(function(root) {
;(function(window) {
'use strict';
/** Backup possible global object */
var oldRoot = root;
/** Backup possible window/global object */
var oldWin = window;
/** Detect free variable `exports` */
var freeExports = typeof exports == 'object' && exports;
/** Detect free variable `global` */
var freeGlobal = typeof global == 'object' && global &&
(global == global.global ? (root = global) : global);
(global == global.global ? (window = global) : global);
/** Opera regexp */
var reOpera = /Opera/;
@@ -23,10 +23,10 @@
var toString = Object.prototype.toString;
/** Detect Java environment */
var java = /Java/.test(getClassOf(root.java)) && root.java;
var java = /Java/.test(getClassOf(window.java)) && window.java;
/** Detect Rhino */
var rhino = java && getClassOf(root.environment) == 'Environment';
var rhino = java && getClassOf(window.environment) == 'Environment';
/** A character to represent alpha */
var alpha = java ? 'a' : '\u03b1';
@@ -35,20 +35,20 @@
var beta = java ? 'b' : '\u03b2';
/** Browser document object */
var doc = root.document || {};
var doc = window.document || {};
/** Used to check for own properties of an object */
var hasOwnProperty = {}.hasOwnProperty;
/** Browser navigator object */
var nav = root.navigator || {};
var nav = window.navigator || {};
/**
* Detect Opera browser
* http://www.howtocreate.co.uk/operaStuff/operaObject.html
* http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
*/
var opera = root.operamini || root.opera;
var opera = window.operamini || window.opera;
/** Opera [[Class]] */
var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);
@@ -65,8 +65,8 @@
* Capitalizes a string value.
*
* @private
* @param {string} string The string to capitalize.
* @returns {string} The capitalized string.
* @param {String} string The string to capitalize.
* @returns {String} The capitalized string.
*/
function capitalize(string) {
string = String(string);
@@ -97,8 +97,8 @@
* Trim and conditionally capitalize string values.
*
* @private
* @param {string} string The string to format.
* @returns {string} The formatted string.
* @param {String} string The string to format.
* @returns {String} The formatted string.
*/
function format(string) {
string = trim(string);
@@ -124,8 +124,8 @@
* Gets the internal [[Class]] of a value.
*
* @private
* @param {*} value The value.
* @returns {string} The [[Class]].
* @param {Mixed} value The value.
* @returns {String} The [[Class]].
*/
function getClassOf(value) {
return value == null
@@ -138,8 +138,8 @@
*
* @private
* @param {Object} object The object to check.
* @param {string} key The key to check for.
* @returns {boolean} Returns `true` if key is a direct property, else `false`.
* @param {String} key The key to check for.
* @returns {Boolean} Returns `true` if key is a direct property, else `false`.
*/
function hasKey() {
// lazy define for others (not as accurate)
@@ -173,9 +173,9 @@
* types of object, function, or unknown.
*
* @private
* @param {*} object The owner of the property.
* @param {string} property The property to check.
* @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
* @param {Mixed} object The owner of the property.
* @param {String} property The property to check.
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
*/
function isHostType(object, property) {
var type = object != null ? typeof object[property] : 'number';
@@ -188,8 +188,8 @@
* spaces optional.
*
* @private
* @param {string} string The string to qualify.
* @returns {string} The qualified string.
* @param {String} string The string to qualify.
* @returns {String} The qualified string.
*/
function qualify(string) {
return String(string).replace(/([ -])(?!$)/g, '$1?');
@@ -201,8 +201,8 @@
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function called per iteration.
* @param {*} accumulator Initial value of the accumulator.
* @returns {*} The accumulator.
* @param {Mixed} accumulator Initial value of the accumulator.
* @returns {Mixed} The accumulator.
*/
function reduce(array, callback) {
var accumulator = null;
@@ -216,8 +216,8 @@
* Removes leading and trailing whitespace from a string.
*
* @private
* @param {string} string The string to trim.
* @returns {string} The trimmed string.
* @param {String} string The string to trim.
* @returns {String} The trimmed string.
*/
function trim(string) {
return String(string).replace(/^ +| +$/g, '');
@@ -229,7 +229,7 @@
* Creates a new platform object.
*
* @memberOf platform
* @param {string} [ua = navigator.userAgent] The user agent string.
* @param {String} [ua = navigator.userAgent] The user agent string.
* @returns {Object} A platform object.
*/
function parse(ua) {
@@ -299,7 +299,6 @@
'WebPositive',
'Opera Mini',
'Opera',
{ 'label': 'Opera', 'pattern': 'OPR' },
'Chrome',
{ 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
@@ -378,7 +377,7 @@
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {null|string} The detected layout engine.
* @returns {String|Null} The detected layout engine.
*/
function getLayout(guesses) {
return reduce(guesses, function(result, guess) {
@@ -393,7 +392,7 @@
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {null|string} The detected manufacturer.
* @returns {String|Null} The detected manufacturer.
*/
function getManufacturer(guesses) {
return reduce(guesses, function(result, value, key) {
@@ -411,7 +410,7 @@
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {null|string} The detected browser name.
* @returns {String|Null} The detected browser name.
*/
function getName(guesses) {
return reduce(guesses, function(result, guess) {
@@ -426,7 +425,7 @@
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {null|string} The detected OS name.
* @returns {String|Null} The detected OS name.
*/
function getOS(guesses) {
return reduce(guesses, function(result, guess) {
@@ -460,7 +459,6 @@
.replace(/Macintosh/, 'Mac OS')
.replace(/_PowerPC/i, ' OS')
.replace(/(OS X) [^ \d]+/i, '$1')
.replace(/Mac (OS X)/, '$1')
.replace(/\/(\d)/, ' $1')
.replace(/_/g, '.')
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
@@ -476,7 +474,7 @@
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {null|string} The detected product name.
* @returns {String|Null} The detected product name.
*/
function getProduct(guesses) {
return reduce(guesses, function(result, guess) {
@@ -505,7 +503,7 @@
*
* @private
* @param {Array} patterns An array of UA patterns.
* @returns {null|string} The detected version.
* @returns {String|Null} The detected version.
*/
function getVersion(patterns) {
return reduce(patterns, function(result, pattern) {
@@ -521,7 +519,7 @@
*
* @name toString
* @memberOf platform
* @returns {string} Returns `platform.description` if available, else an empty string.
* @returns {String} Returns `platform.description` if available, else an empty string.
*/
function toStringPlatform() {
return this.description || '';
@@ -557,7 +555,7 @@
}
// detect Android browsers
else if (manufacturer && manufacturer != 'Google' &&
((/Chrome/.test(name) && !/Mobile Safari/.test(ua)) || /Vita/.test(product))) {
/Chrome|Vita/.test(name + ';' + product)) {
name = 'Android Browser';
os = /Android/.test(os) ? os : 'Android';
}
@@ -577,7 +575,7 @@
// detect non-Opera versions (order is important)
if (!version) {
version = getVersion([
'(?:Cloud9|CriOS|CrMo|Opera ?Mini|OPR|Raven|Silk(?!/[\\d.]+$))',
'(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
'Version',
qualify(name),
'(?:Firefox|Minefield|NetFront)'
@@ -587,9 +585,9 @@
if (layout == 'iCab' && parseFloat(version) > 3) {
layout = ['WebKit'];
} else if ((data =
/Opera/.test(name) && (/OPR/.test(ua) ? 'Blink' : 'Presto') ||
/Opera/.test(name) && 'Presto' ||
/\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
!layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident')
!layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')
)) {
layout = [data];
}
@@ -597,7 +595,7 @@
if (useFeatures) {
// detect server-side environments
// Rhino has a global function while others have a global object
if (isHostType(root, 'global')) {
if (isHostType(window, 'global')) {
if (java) {
data = java.lang.System;
arch = data.getProperty('os.arch');
@@ -605,7 +603,7 @@
}
if (freeExports) {
// if `thisBinding` is the [ModuleScope]
if (thisBinding == oldRoot && typeof system == 'object' && (data = [system])[0]) {
if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
os || (os = data[0].os || null);
try {
data[1] = require('ringo/engine').version;
@@ -632,12 +630,12 @@
}
}
// detect Adobe AIR
else if (getClassOf((data = root.runtime)) == 'ScriptBridgingProxyObject') {
else if (getClassOf((data = window.runtime)) == 'ScriptBridgingProxyObject') {
name = 'Adobe AIR';
os = data.flash.system.Capabilities.os;
}
// detect PhantomJS
else if (getClassOf((data = root.phantom)) == 'RuntimeObject') {
else if (getClassOf((data = window.phantom)) == 'RuntimeObject') {
name = 'PhantomJS';
version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
}
@@ -690,7 +688,7 @@
description.unshift('desktop mode');
}
// add mobile postfix
else if ((name == 'Chrome' || name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&
else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&
(os == 'Windows CE' || /Mobi/i.test(ua))) {
name += ' Mobile';
}
@@ -798,7 +796,7 @@
name = 'Chrome Mobile';
version = null;
if (/OS X/.test(os)) {
if (/Mac OS X/.test(os)) {
manufacturer = 'Apple';
os = 'iOS 4.3+';
} else {
@@ -870,7 +868,7 @@
* The browser/environment version.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'version': name && version && (description.unshift(version), version),
@@ -878,7 +876,7 @@
* The name of the browser/environment.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'name': name && (description.unshift(name), name),
@@ -898,7 +896,7 @@
* The CPU architecture the OS is built for.
*
* @memberOf platform.os
* @type number|null
* @type Number|Null
*/
'architecture': null,
@@ -906,7 +904,7 @@
* The family of the OS.
*
* @memberOf platform.os
* @type string|null
* @type String|Null
*/
'family': null,
@@ -914,7 +912,7 @@
* The version of the OS.
*
* @memberOf platform.os
* @type string|null
* @type String|Null
*/
'version': null,
@@ -922,7 +920,7 @@
* Returns the OS string.
*
* @memberOf platform.os
* @returns {string} The OS string.
* @returns {String} The OS string.
*/
'toString': function() { return 'null'; }
},
@@ -931,7 +929,7 @@
* The platform description.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'description': description.length ? description.join(' ') : ua,
@@ -939,7 +937,7 @@
* The name of the browser layout engine.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'layout': layout && layout[0],
@@ -947,7 +945,7 @@
* The name of the product's manufacturer.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'manufacturer': manufacturer,
@@ -955,7 +953,7 @@
* The alpha/beta release indicator.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'prerelease': prerelease,
@@ -963,7 +961,7 @@
* The name of the product hosting the browser.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'product': product,
@@ -971,7 +969,7 @@
* The browser's user agent string.
*
* @memberOf platform
* @type string|null
* @type String|Null
*/
'ua': ua,
@@ -986,7 +984,7 @@
/*--------------------------------------------------------------------------*/
// expose platform
// some AMD build optimizers, like r.js, check for condition patterns like the following:
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// define as an anonymous module so, through path mapping, it can be aliased
define(function() {
@@ -1002,6 +1000,6 @@
}
// in a browser or Rhino
else {
root.platform = parse();
window.platform = parse();
}
}(this));

60
vendor/qunit-clib/README.md vendored Normal file
View File

@@ -0,0 +1,60 @@
# QUnit CLIB <sup>v1.3.0</sup>
## command-line interface boilerplate
QUnit CLIB helps extend QUnits CLI support to many common CLI environments.
## Screenshot
![QUnit CLIB brings QUnit to your favorite shell.](http://i.imgur.com/jpu9l.png)
## Support
QUnit CLIB has been tested in at least Node.js 0.4.8-0.10.7, Narwhal 0.3.2, PhantomJS 1.9.0, RingoJS 0.9, and Rhino 1.7RC5.
## Usage
```js
;(function(window) {
'use strict';
// use a single "load" function
var load = typeof require == 'function' ? require : window.load;
// load QUnit and CLIB if needed
var QUnit = (function() {
var noop = Function.prototype;
return window.QUnit || (
window.addEventListener || (window.addEventListener = noop),
window.setTimeout || (window.setTimeout = noop),
window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit,
(load('../vendor/qunit-clib/qunit-clib.js') || { 'runInContext': noop }).runInContext(window),
addEventListener === noop && delete window.addEventListener,
window.QUnit
);
}());
// explicitly call `QUnit.module()` instead of `module()`
// in case we are in a CLI environment
QUnit.module('A Test Module');
test('A Test', function() {
// ...
});
// call `QUnit.start()` for Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
if (!window.document || window.phantom) {
QUnit.start();
}
}(typeof global == 'object' && global || this));
```
## Footnotes
1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout`
## Author
| [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](http://twitter.com/jdalton "Follow @jdalton on Twitter") |
|---|
| [John-David Dalton](http://allyoucanleet.com/) |

View File

@@ -4,16 +4,16 @@
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
* Available under MIT license <http://mths.be/mit>
*/
;(function(root) {
;(function(window) {
'use strict';
/** Detect free variable `exports` */
var freeExports = typeof exports == 'object' && exports;
/** Detect free variable `global`, from Node.js or Browserified code, and use it as `root` */
/** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
window = freeGlobal;
}
/*--------------------------------------------------------------------------*/
@@ -34,11 +34,11 @@
* Schedules timer-based callbacks.
*
* @private
* @param {Function|string} fn The function to call.
* @param {number} delay The number of milliseconds to delay the `fn` call.
* @param {Function|String} fn The function to call.
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @param {boolean} repeated A flag to specify whether `fn` is called repeatedly.
* @returns {number} The the ID of the timeout.
* @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
* @returns {Number} The the ID of the timeout.
*/
function schedule(fn, delay, args, repeated) {
// Rhino 1.7RC4 will error assigning `task` below
@@ -70,7 +70,7 @@
* Clears the delay set by `setInterval` or `setTimeout`.
*
* @memberOf context
* @param {number} id The ID of the timeout to be cleared.
* @param {Number} id The ID of the timeout to be cleared.
*/
function clearTimer(id) {
if (ids[id]) {
@@ -84,10 +84,10 @@
* Executes a code snippet or function repeatedly, with a delay between each call.
*
* @memberOf context
* @param {Function|string} fn The function to call or string to evaluate.
* @param {number} delay The number of milliseconds to delay each `fn` call.
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {number} The the ID of the timeout.
* @returns {Number} The the ID of the timeout.
*/
function setInterval(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2), true);
@@ -97,10 +97,10 @@
* Executes a code snippet or a function after specified delay.
*
* @memberOf context
* @param {Function|string} fn The function to call or string to evaluate.
* @param {number} delay The number of milliseconds to delay the `fn` call.
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {number} The the ID of the timeout.
* @returns {Number} The the ID of the timeout.
*/
function setTimeout(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2));
@@ -108,48 +108,14 @@
/*------------------------------------------------------------------------*/
/** Used to report the test module for failing tests */
var moduleName,
modulePrinted;
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
var console = context.console || (context.console = { 'log': context.print });
/** Used as a horizontal rule in console output */
var hr = '----------------------------------------';
/** Used by `logInline` to clear previously logged messages */
var prevLine = '';
/** Shorten `context.QUnit.QUnit` to `context.QUnit` */
var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit;
/**
* Logs an inline message to standard output.
*
* @private
* @param {string} text The text to log.
*/
var logInline = (function() {
// exit early if not Node.js
if (!(typeof process == 'object' && process &&
process.on && process.stdout && process.platform != 'win32')) {
return function() {};
}
// cleanup any inline logs when exited via `ctrl+c`
process.on('SIGINT', function() {
logInline('');
process.exit();
});
return function(text) {
var blankLine = Array(prevLine.length + 1).join(' ');
if (text.length > hr.length) {
text = text.slice(0, hr.length - 3) + '...';
}
prevLine = text;
process.stdout.write(text + blankLine.slice(text.length) + '\r');
}
}());
/** Used as a horizontal rule in console output */
var hr = '----------------------------------------';
/**
* A logging callback triggered when all testing is completed.
@@ -167,30 +133,26 @@
}
ran = true;
logInline('');
console.log(hr);
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
console.log(' Finished in ' + details.runtime + ' milliseconds.');
console.log(hr);
// exit out of Narhwal, Rhino, or Ringo
try {
quit();
} catch(e) { }
// exit out of Node.js or PhantomJS
try {
var process = context.process || context.phantom;
if (details.failed) {
console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
process.exit(1);
} else {
process.exit(0);
}
} catch(e) { }
// exit out of Narwhal, Rhino, or RingoJS
try {
if (details.failed) {
java.lang.System.exit(1);
} else {
quit();
}
} catch(e) { }
};
}());
@@ -224,11 +186,9 @@
* @param {Object} details An object with property `name`.
*/
QUnit.moduleStart(function(details) {
var newModuleName = details.name;
if (moduleName != newModuleName) {
moduleName = newModuleName;
modulePrinted = false;
}
console.log(hr);
console.log(details.name);
console.log(hr);
});
/**
@@ -237,7 +197,7 @@
* @memberOf QUnit
* @type Function
* @param {Object} object The object to stringify.
* @returns {string} The result string.
* @returns {String} The result string.
*/
QUnit.jsDump.parsers.object = (function() {
var func = QUnit.jsDump.parsers.object;
@@ -264,19 +224,13 @@
testName = details.name;
if (details.failed > 0) {
logInline('');
if (!modulePrinted) {
modulePrinted = true;
console.log(hr);
console.log(moduleName);
console.log(hr);
}
console.log(' FAIL - '+ testName);
assertions.forEach(function(value) {
console.log(' ' + value);
});
} else {
logInline('Testing ' + moduleName + '...');
}
else {
console.log(' PASS - ' + testName);
}
assertions.length = 0;
});
@@ -290,7 +244,7 @@
QUnit.config.testStats = {
/**
* An array of test summaries.
* An array of test summaries (pipe separated).
*
* @memberOf QUnit.config.testStats
* @type Array
@@ -309,23 +263,10 @@
slice = Array.prototype.slice,
timer = new java.util.Timer;
(function() {
var getDescriptor = Object.getOwnPropertyDescriptor || function() {
return { 'writable': true };
};
var descriptor;
if ((!context.clearInterval || ((descriptor = getDescriptor(context, 'clearInterval')) && (descriptor.writable || descriptor.set))) &&
(!context.setInterval || ((descriptor = getDescriptor(context, 'setInterval')) && (descriptor.writable || descriptor.set)))) {
context.clearInterval = clearTimer;
context.setInterval = setInterval;
}
if ((!context.clearTimeout || ((descriptor = getDescriptor(context, 'clearTimeout')) && (descriptor.writable || descriptor.set))) &&
(!context.setTimeout || ((descriptor = getDescriptor(context, 'setTimeout')) && (descriptor.writable || descriptor.set)))) {
context.clearTimeout = clearTimer;
context.setTimeout = setTimeout;
}
}());
context.clearInterval =
context.clearTimeout = clearTimer;
context.setInterval = setInterval;
context.setTimeout = setTimeout;
} catch(e) { }
// expose shortcuts
@@ -335,19 +276,17 @@
context[methodName] = QUnit[methodName];
});
// must call `QUnit.start()` in the test file if not loaded in a browser
if (!context.document || context.phantom) {
QUnit.config.autostart = false;
QUnit.init();
}
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
// Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
QUnit.init();
}
/*--------------------------------------------------------------------------*/
// expose QUnit CLIB
if (freeExports && !freeExports.nodeType) {
if (freeExports) {
freeExports.runInContext = runInContext;
} else {
runInContext(root);
runInContext(window);
}
}(this));

View File

@@ -1,21 +0,0 @@
Copyright 2013 jQuery Foundation and other contributors
http://jquery.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.

62
vendor/qunit/README.md vendored Normal file
View File

@@ -0,0 +1,62 @@
[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
================================
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
project to test its code and plugins but is capable of testing any generic
JavaScript code (and even capable of testing JavaScript code on the server-side).
QUnit is especially useful for regression testing: Whenever a bug is reported,
write a test that asserts the existence of that particular bug. Then fix it and
commit both. Every time you work on the code again, run the tests. If the bug
comes up again - a regression - you'll spot it immediately and know how to fix
it, because you know what code you just changed.
Having good unit test coverage makes safe refactoring easy and cheap. You can
run the tests after each small refactoring step and always know what change
broke something.
QUnit is similar to other unit testing frameworks like JUnit, but makes use of
the features JavaScript provides and helps with testing code in the browser, e.g.
with its stop/start facilities for testing asynchronous code.
If you are interested in helping developing QUnit, you are in the right place.
For related discussions, visit the
[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
Development
-----------
To submit patches, fork the repository, create a branch for the change. Then implement
the change, run `grunt` to lint and test it, then commit, push and create a pull request.
Include some background for the change in the commit message and `Fixes #nnn`, referring
to the issue number you're addressing.
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
grunt binary. For additional grunt tasks, also run `npm install`.
Releases
--------
Install git-extras and run `git changelog` to update History.md.
Update qunit/qunit.js|css and package.json to the release version, commit and
tag, update them again to the next version, commit and push commits and tags
(`git push --tags origin master`).
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
or whitespace cleanups.
To upload to code.jquery.com (replace $version accordingly), ssh to code.origin.jquery.com:
cp qunit/qunit.js /var/www/html/code.jquery.com/qunit/qunit-$version.js
cp qunit/qunit.css /var/www/html/code.jquery.com/qunit/qunit-$version.css
Then update /var/www/html/code.jquery.com/index.html and purge it with:
curl -s http://code.origin.jquery.com/?reload
Update web-base-template to link to those files for qunitjs.com.
Publish to npm via
npm publish

51
vendor/requirejs/README.md vendored Normal file
View File

@@ -0,0 +1,51 @@
# RequireJS
RequireJS loads plain JavaScript files as well as more defined modules. It is
optimized for in-browser use, including in
[a Web Worker](http://requirejs.org/docs/api.html#webworker), but it can be used
in other JavaScript environments, like Rhino and
[Node](http://requirejs.org/docs/node.html). It implements the
[Asynchronous Module](https://github.com/amdjs/amdjs-api/wiki/AMD)
API.
RequireJS uses plain script tags to load modules/files, so it should allow for
easy debugging. It can be used
[simply to load existing JavaScript files](http://requirejs.org/docs/api.html#jsfiles),
so you can add it to your existing project without having to re-write your
JavaScript files.
RequireJS includes [an optimization tool](http://requirejs.org/docs/optimization.html)
you can run as part of your packaging steps for deploying your code. The
optimization tool can combine and minify your JavaScript files to allow for
better performance.
If the JavaScript file defines a JavaScript module via
[define()](http://requirejs.org/docs/api.html#define), then there are other benefits
RequireJS can offer: [improvements over traditional CommonJS modules](http://requirejs.org/docs/commonjs.html)
and [loading multiple versions](http://requirejs.org/docs/api.html#multiversion)
of a module in a page. RequireJS also has a plugin system that supports features like
[i18n string bundles](http://requirejs.org/docs/api.html#i18n), and
[text file dependencies](http://requirejs.org/docs/api.html#text).
RequireJS does not have any dependencies on a JavaScript framework.
It is dual-licensed -- new BSD or MIT.
The standard require.js file is around 5.5KB when minified via Closure Compiler
and gzipped.
RequireJS works in IE 6+, Firefox 2+, Safari 3.2+, Chrome 3+, and Opera 10+.
[Latest Release](http://requirejs.org/docs/download.html)
## Directories
* **dist**: Scripts and assets to generate the requirejs.org docs, and for
generating a require.js release.
* **docs**: The raw HTML files for the requirejs.org docs. Only includes the
body of each page. Files in **dist** are used to generate a complete HTML page.
* **tests**: Tests for require.js.
* **testBaseUrl.js**: A file used in the tests inside **tests**. Purposely
placed outside the tests directory for testing paths that go outside a baseUrl.
* **updatesubs.sh**: Updates projects that depend on require.js Assumes the
projects are siblings to this directory and have specific names. Useful to
copy require.js to dependent projects easily while in development.

View File

@@ -1,5 +1,5 @@
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.1.9 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* @license RequireJS 2.1.6 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@@ -12,7 +12,7 @@ var requirejs, require, define;
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.1.9',
version = '2.1.6',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@@ -22,7 +22,7 @@ var requirejs, require, define;
hasOwn = op.hasOwnProperty,
ap = Array.prototype,
apsp = ap.splice,
isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
//PS3 indicates loaded and complete, but need to wait for complete
//specifically. Sequence is 'loading', 'loaded', execution,
@@ -373,6 +373,7 @@ var requirejs, require, define;
function hasPathFallback(id) {
var pathConfig = getOwn(config.paths, id);
if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
removeScript(id);
//Pop off the first array value, since it failed, and
//retry
pathConfig.shift();
@@ -1463,8 +1464,6 @@ var requirejs, require, define;
var map = makeModuleMap(id, relMap, true),
mod = getOwn(registry, id);
removeScript(id);
delete defined[id];
delete urlFetched[map.url];
delete undefEvents[id];
@@ -1610,7 +1609,7 @@ var requirejs, require, define;
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js'));
url += (ext || (/\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
}
@@ -1795,19 +1794,6 @@ var requirejs, require, define;
*/
req.onError = defaultOnError;
/**
* Creates the node for the load command. Only used in browser envs.
*/
req.createNode = function (config, moduleName, url) {
var node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
return node;
};
/**
* Does the request to load a module for the browser case.
* Make this a separate function to allow other environments
@@ -1822,7 +1808,12 @@ var requirejs, require, define;
node;
if (isBrowser) {
//In the browser so use a script tag
node = req.createNode(config, moduleName, url);
node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
@@ -1919,7 +1910,7 @@ var requirejs, require, define;
}
//Look for a data-main script attribute, which could also adjust the baseUrl.
if (isBrowser && !cfg.skipDataMain) {
if (isBrowser) {
//Figure out baseUrl. Get it from the script tag with require.js in it.
eachReverse(scripts(), function (script) {
//Set the 'head' where we can append children by

View File

@@ -1,5 +1,4 @@
Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors
Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

19
vendor/underscore/README.md vendored Normal file
View File

@@ -0,0 +1,19 @@
__
/\ \ __
__ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
\ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
\/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
\ \____/
\/___/
Underscore.js is a utility-belt library for JavaScript that provides
support for the usual functional suspects (each, map, reduce, filter...)
without extending any core JavaScript objects.
For Docs, License, Tests, and pre-packed downloads, see:
http://underscorejs.org
Many thanks to our contributors:
https://github.com/documentcloud/underscore/contributors

View File

@@ -65,8 +65,6 @@ $(document).ready(function() {
deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays');
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
deepEqual(result, [1,2,3,4], 'works on an arguments object');
list = [[1], [2], [3], [[4]]];
deepEqual(_.flatten(list, true), [1, 2, 3, [4]], 'can shallowly flatten arrays containing only other arrays');
});
test("without", function() {
@@ -75,7 +73,7 @@ $(document).ready(function() {
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
equal(result.join(', '), '2, 3, 4', 'works on an arguments object');
list = [{one : 1}, {two : 2}];
var list = [{one : 1}, {two : 2}];
ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');
ok(_.without(list, list[0]).length == 1, 'ditto.');
});
@@ -84,17 +82,17 @@ $(document).ready(function() {
var list = [1, 2, 1, 3, 1, 4];
equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');
list = [1, 1, 1, 2, 2, 3];
var list = [1, 1, 1, 2, 2, 3];
equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');
list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];
var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];
var iterator = function(value) { return value.name; };
equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
equal(_.map(_.uniq(list, iterator), iterator).join(', '), '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];
var iterator = function(value) { return value +1; };
var list = [1, 2, 2, 3, 4, 4];
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);
@@ -107,31 +105,21 @@ $(document).ready(function() {
equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');
equal(result.join(''), 'moe', 'works on an arguments object');
var theSixStooges = ['moe', 'moe', 'curly', 'curly', 'larry', 'larry'];
equal(_.intersection(theSixStooges, leaders).join(''), 'moe', 'returns a duplicate-free array');
});
test("union", function() {
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
var args = null;
(function(){ args = arguments; })(1, 2, 3);
result = _.union(args, [2, 30, 1], [1, 40]);
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
result = _.union(null, [1, 2, 3]);
deepEqual(result, [null, 1, 2, 3]);
});
test("difference", function() {
var result = _.difference([1, 2, 3], [2, 30, 40]);
equal(result.join(' '), '1 3', 'takes the difference of two arrays');
result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
equal(result.join(' '), '3 4', 'takes the difference of three arrays');
});
@@ -139,17 +127,6 @@ $(document).ready(function() {
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
var stooges = _.zip(names, ages, leaders);
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
stooges = _.zip(['moe',30, 'stooge 1'],['larry',40, 'stooge 2'],['curly',50, 'stooge 3']);
deepEqual(stooges, [['moe','larry','curly'],[30,40,50], ['stooge 1', 'stooge 2', 'stooge 3']], 'zipped pairs');
// 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']);
deepEqual(stooges, [['moe','larry','curly'],[30,40,50], [undefined, undefined, 'extra data']], 'zipped pairs with empties');
var empty = _.zip([]);
deepEqual(empty, [], 'unzipped empty');
});
test('object', function() {
@@ -175,8 +152,7 @@ $(document).ready(function() {
equal(result, 1, 'works on an arguments object');
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
var num = 35;
numbers = [10, 20, 30, 40, 50];
var numbers = [10, 20, 30, 40, 50], num = 35;
var index = _.indexOf(numbers, num, true);
equal(index, -1, '35 is not in the list');
@@ -203,7 +179,7 @@ $(document).ready(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);
equal(result, 5, 'works on an arguments object');
equal(_.lastIndexOf(null, 2), -1, 'handles nulls properly');
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
var index = _.lastIndexOf(numbers, 2, 2);

View File

@@ -17,15 +17,15 @@ $(document).ready(function() {
hash[l]++;
return hash;
}, {}).value();
ok(counts.a == 16 && counts.e == 10, 'counted all the letters in the song');
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
});
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;
return n % 2 == 0;
}).reject(function(n) {
return n % 4 === 0;
return n % 4 == 0;
}).sortBy(function(n) {
return -n;
}).value();
@@ -35,9 +35,9 @@ $(document).ready(function() {
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;
return n % 2 == 0;
}).reject(function(n) {
return n % 4 === 0;
return n % 4 == 0;
}).sortBy(function(n) {
return -n;
}).value();
@@ -56,10 +56,4 @@ $(document).ready(function() {
equal(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.');
});
test("chaining works in small stages", function() {
var o = _([1, 2, 3, 4]).chain();
deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]);
deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]);
});
});

View File

@@ -76,16 +76,13 @@ $(document).ready(function() {
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; });
equal(sum, 6, 'default initial value');
var prod = _.reduce([1, 2, 3, 4], function(prod, num){ return prod * num; });
equal(prod, 24, 'can reduce via multiplication');
var ifnull;
try {
_.reduce(null, function(){});
} catch (ex) {
ifnull = ex;
}
ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly');
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
@@ -108,7 +105,7 @@ $(document).ready(function() {
} catch (ex) {
ifnull = ex;
}
ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly');
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; });
equal(sum, 6, 'default initial value on object');
@@ -261,11 +258,6 @@ $(document).ready(function() {
result = _.where(list, {b: 2});
equal(result.length, 2);
equal(result[0].a, 1);
result = _.where(list, {a: 1}, true);
equal(result.b, 2, "Only get the first object matched.")
result = _.where(list, {a: 1}, false);
equal(result.length, 3);
});
test('findWhere', function() {
@@ -274,12 +266,6 @@ $(document).ready(function() {
deepEqual(result, {a: 1, b: 2});
result = _.findWhere(list, {b: 4});
deepEqual(result, {a: 1, b: 4});
result = _.findWhere(list, {c:1})
ok(_.isUndefined(result), "undefined when not found");
result = _.findWhere([], {c:1});
ok(_.isUndefined(result), "undefined when searching empty list");
});
test('max', function() {
@@ -375,32 +361,6 @@ $(document).ready(function() {
var grouped = _.groupBy(array);
equal(grouped['1'].length, 2);
equal(grouped['3'].length, 1);
var matrix = [
[1,2],
[1,3],
[2,3]
];
deepEqual(_.groupBy(matrix, 0), {1: [[1,2], [1,3]], 2: [[2,3]]})
deepEqual(_.groupBy(matrix, 1), {2: [[1,2]], 3: [[1,3], [2,3]]})
});
test('indexBy', function() {
var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; });
equal(parity['true'], 4);
equal(parity['false'], 5);
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
var grouped = _.indexBy(list, 'length');
equal(grouped['3'], 'ten');
equal(grouped['4'], 'nine');
equal(grouped['5'], 'eight');
var array = [1, 2, 1, 2, 3];
var grouped = _.indexBy(array);
equal(grouped['1'], 1);
equal(grouped['2'], 2);
equal(grouped['3'], 3);
});
test('countBy', function() {
@@ -457,19 +417,6 @@ $(document).ready(function() {
equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');
});
test('sample', function() {
var numbers = _.range(10);
var all_sampled = _.sample(numbers, 10).sort();
equal(all_sampled.join(','), numbers.join(','), 'contains the same members before and after sample');
all_sampled = _.sample(numbers, 20).sort();
equal(all_sampled.join(','), numbers.join(','), 'also works when sampling more objects than are present');
ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element returns something from the array');
strictEqual(_.sample([]), undefined, 'sampling empty array with no number returns undefined');
notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number returns an empty array');
notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks returns an empty array');
deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks returns an empty array');
});
test('toArray', function() {
ok(!_.isArray(arguments), 'arguments object is not an array');
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
@@ -491,7 +438,6 @@ $(document).ready(function() {
test('size', function() {
equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');
equal(_.size($('<div>').add('<span>').add('<span>')), 3, 'can compute the size of jQuery objects');
var func = function() {
return _.size(arguments);
@@ -499,8 +445,7 @@ $(document).ready(function() {
equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object');
equal(_.size('hello'), 5, 'can compute the size of a string literal');
equal(_.size(new String('hello')), 5, 'can compute the size of string object');
equal(_.size('hello'), 5, 'can compute the size of a string');
equal(_.size(null), 0, 'handles nulls');
});

View File

@@ -34,10 +34,7 @@ $(document).ready(function() {
// To test this with a modern browser, set underscore's nativeBind to undefined
var F = function () { return this; };
var Boundf = _.bind(F, {hello: "moe curly"});
var newBoundf = new Boundf();
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");
});
test("partial", function() {
@@ -66,21 +63,18 @@ $(document).ready(function() {
getName : function() { return 'name: ' + this.name; },
sayHi : function() { return 'hi: ' + this.name; }
};
raises(function() { _.bindAll(moe); }, Error, 'throws an error for bindAll with no functions named');
_.bindAll(moe, 'sayHi');
_.bindAll(moe);
curly.sayHi = moe.sayHi;
equal(curly.sayHi(), 'hi: moe');
equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
});
test("memoize", function() {
var fib = function(n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2);
};
var fastFib = _.memoize(fib);
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
fib = _.memoize(fib); // Redefine `fib` for memoization
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results');
var o = function(str) {
return str;
@@ -142,31 +136,17 @@ $(document).ready(function() {
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 64);
});
asyncTest("more throttling", 3, function() {
var counter = 0;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 30);
throttledIncr(); throttledIncr();
ok(counter == 1);
_.delay(function(){
ok(counter == 2);
throttledIncr();
ok(counter == 3);
start();
}, 85);
});
asyncTest("throttle repeatedly with results", 6, function() {
var counter = 0;
var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 100);
var throttledIncr = _.throttle(incr, 64);
var results = [];
var saveResult = function() { results.push(throttledIncr()); };
saveResult(); saveResult();
_.delay(saveResult, 50);
_.delay(saveResult, 150);
_.delay(saveResult, 160);
_.delay(saveResult, 230);
_.delay(saveResult, 32);
_.delay(saveResult, 80);
_.delay(saveResult, 96);
_.delay(saveResult, 144);
_.delay(function() {
equal(results[0], 1, "incr was called once");
equal(results[1], 1, "incr was throttled");
@@ -175,7 +155,7 @@ $(document).ready(function() {
equal(results[4], 2, "incr was throttled");
equal(results[5], 3, "incr was called trailing");
start();
}, 300);
}, 192);
});
asyncTest("throttle triggers trailing call when invoked repeatedly", 2, function() {
@@ -197,77 +177,6 @@ $(document).ready(function() {
}, 96);
});
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();
ok(counter === 0);
_.delay(function() {
ok(counter == 1);
start();
}, 96);
});
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});
throttledIncr();
_.delay(throttledIncr, 50);
_.delay(throttledIncr, 60);
_.delay(throttledIncr, 200);
ok(counter === 0);
_.delay(function() {
ok(counter == 1);
}, 250);
_.delay(function() {
ok(counter == 2);
start();
}, 350);
});
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();
ok(counter <= 3);
_.delay(function() {
ok(counter <= 4);
start();
}, 200);
});
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();
ok(counter === 1);
_.delay(function() {
ok(counter == 1);
throttledIncr(); throttledIncr();
ok(counter == 2);
_.delay(function() {
ok(counter == 2);
start();
}, 96);
}, 96);
});
asyncTest("debounce", 1, function() {
var counter = 0;
var incr = function(){ counter++; };
@@ -312,18 +221,10 @@ $(document).ready(function() {
equal(num, 1);
});
test("Recursive onced function.", 1, function() {
var f = _.once(function(){
ok(true);
f();
});
f();
});
test("wrap", function() {
var greet = function(name){ return "hi: " + name; };
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
equal(backwards('moe'), 'hi: moe eom', 'wrapped the salutation function');
equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
var inner = function(){ return "Hello "; };
var obj = {name : "Moe"};
@@ -358,8 +259,7 @@ $(document).ready(function() {
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");
equal(testAfter(0, 0), 1, "after(0) should fire immediately");
});
});

View File

@@ -46,13 +46,13 @@ $(document).ready(function() {
var result;
equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');
equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');
equal(_.extend({x:'x'}, {a:'b'}).x, 'x', "properties not in source don't get overriden");
equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden');
result = _.extend({x:'x'}, {a:'a'}, {b:'b'});
ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects');
result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'});
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
result = _.extend({}, {a: void 0, b: null});
equal(_.keys(result).join(''), 'ab', 'extend copies undefined values');
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
try {
result = {};
@@ -92,13 +92,12 @@ $(document).ready(function() {
test("defaults", function() {
var result;
var options = {zero: 0, one: 1, empty: "", nan: NaN, nothing: null};
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
_.defaults(options, {zero: 1, one: 10, twenty: 20, nothing: 'str'});
_.defaults(options, {zero: 1, one: 10, twenty: 20});
equal(options.zero, 0, 'value exists');
equal(options.one, 1, 'value exists');
equal(options.twenty, 20, 'default applied');
equal(options.nothing, null, "null isn't overridden");
_.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"});
equal(options.empty, "", 'value exists');
@@ -432,19 +431,15 @@ $(document).ready(function() {
});
test("isArray", function() {
ok(!_.isArray(undefined), 'undefined vars are not arrays');
ok(!_.isArray(arguments), 'the arguments object is not an array');
ok(_.isArray([1, 2, 3]), 'but arrays are');
ok(_.isArray(iArray), 'even from another frame');
});
test("isString", function() {
var obj = new String("I am a string object");
ok(!_.isString(document.body), 'the document body is not a string');
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
ok(_.isString(iString), 'even from another frame');
ok(_.isString("I am a string literal"), 'string literals are');
ok(_.isString(obj), 'so are String objects');
});
test("isNumber", function() {
@@ -473,12 +468,10 @@ $(document).ready(function() {
});
test("isFunction", function() {
ok(!_.isFunction(undefined), 'undefined vars are not functions');
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
ok(!_.isFunction('moe'), 'strings are not functions');
ok(_.isFunction(_.isFunction), 'but functions are');
ok(_.isFunction(iFunction), 'even from another frame');
ok(_.isFunction(function(){}), 'even anonymous ones');
});
test("isDate", function() {

View File

@@ -55,10 +55,6 @@ $(document).ready(function() {
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
// collects return values
ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values");
deepEqual(_.times(0, _.identity), []);
deepEqual(_.times(-1, _.identity), []);
deepEqual(_.times(parseFloat('-Infinity'), _.identity), []);
});
test("mixin", function() {
@@ -73,7 +69,6 @@ $(document).ready(function() {
test("_.escape", function() {
equal(_.escape("Curly & Moe"), "Curly &amp; Moe");
equal(_.escape('<a href="http://moe.com">Curly & Moe\'s</a>'), '&lt;a href=&quot;http://moe.com&quot;&gt;Curly &amp; Moe&#x27;s&lt;/a&gt;');
equal(_.escape("Curly &amp; Moe"), "Curly &amp;amp; Moe");
equal(_.escape(null), '');
});
@@ -81,7 +76,6 @@ $(document).ready(function() {
test("_.unescape", function() {
var string = "Curly & Moe";
equal(_.unescape("Curly &amp; Moe"), string);
equal(_.unescape('&lt;a href=&quot;http://moe.com&quot;&gt;Curly &amp; Moe&#x27;s&lt;/a&gt;'), '<a href="http://moe.com">Curly & Moe\'s</a>');
equal(_.unescape("Curly &amp;amp; Moe"), "Curly &amp; Moe");
equal(_.unescape(null), '');
equal(_.unescape(_.escape(string)), string);
@@ -213,7 +207,7 @@ $(document).ready(function() {
strictEqual(_.result(obj, 'x'), 'x');
strictEqual(_.result(obj, 'y'), 'x');
strictEqual(_.result(obj, 'z'), undefined);
strictEqual(_.result(null, 'x'), undefined);
strictEqual(_.result(null, 'x'), null);
});
test('_.templateSettings.variable', function() {

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
// Underscore.js 1.5.2
// Underscore.js 1.4.4
// http://underscorejs.org
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// (c) 2009-2011 Jeremy Ashkenas, DocumentCloud Inc.
// (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function() {
@@ -8,7 +9,7 @@
// Baseline setup
// --------------
// Establish the root object, `window` in the browser, or `exports` on the server.
// Establish the root object, `window` in the browser, or `global` on the server.
var root = this;
// Save the previous value of the `_` variable.
@@ -65,7 +66,7 @@
}
// Current version.
_.VERSION = '1.5.2';
_.VERSION = '1.4.4';
// Collection Functions
// --------------------
@@ -78,13 +79,14 @@
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, length = obj.length; i < length; i++) {
for (var i = 0, l = obj.length; i < l; i++) {
if (iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
for (var key in obj) {
if (_.has(obj, key)) {
if (iterator.call(context, obj[key], key, obj) === breaker) return;
}
}
}
};
@@ -283,8 +285,7 @@
return result.value;
};
// Shuffle an array, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/FisherYates_shuffle).
// Shuffle an array.
_.shuffle = function(obj) {
var rand;
var index = 0;
@@ -297,16 +298,6 @@
return shuffled;
};
// Sample **n** random values from an array.
// If **n** is not specified, returns a single random element from the array.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (arguments.length < 2 || guard) {
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
};
// An internal function to generate lookup iterators.
var lookupIterator = function(value) {
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
@@ -317,9 +308,9 @@
var iterator = lookupIterator(value);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
index: index,
criteria: iterator.call(context, value, index, list)
value : value,
index : index,
criteria : iterator.call(context, value, index, list)
};
}).sort(function(left, right) {
var a = left.criteria;
@@ -328,41 +319,38 @@
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
return left.index < right.index ? -1 : 1;
}), 'value');
};
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
return function(obj, value, context) {
var result = {};
var iterator = value == null ? _.identity : lookupIterator(value);
each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj);
behavior(result, key, value);
});
return result;
};
var group = function(obj, value, context, behavior) {
var result = {};
var iterator = lookupIterator(value == null ? _.identity : value);
each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj);
behavior(result, key, value);
});
return result;
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, key, value) {
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_.indexBy = group(function(result, key, value) {
result[key] = value;
});
_.groupBy = function(obj, value, context) {
return group(obj, value, context, function(result, key, value) {
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
});
};
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_.countBy = group(function(result, key) {
_.has(result, key) ? result[key]++ : result[key] = 1;
});
_.countBy = function(obj, value, context) {
return group(obj, value, context, function(result, key) {
if (!_.has(result, key)) result[key] = 0;
result[key]++;
});
};
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
@@ -399,7 +387,7 @@
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0;
return (n == null) || guard ? array[0] : slice.call(array, 0, n);
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
};
// Returns everything but the last entry of the array. Especially useful on
@@ -414,10 +402,10 @@
// values in the array. The **guard** check allows it to work with `_.map`.
_.last = function(array, n, guard) {
if (array == null) return void 0;
if ((n == null) || guard) {
return array[array.length - 1];
} else {
if ((n != null) && !guard) {
return slice.call(array, Math.max(array.length - n, 0));
} else {
return array[array.length - 1];
}
};
@@ -436,9 +424,6 @@
// Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, output) {
if (shallow && _.every(input, _.isArray)) {
return concat.apply(output, input);
}
each(input, function(value) {
if (_.isArray(value) || _.isArguments(value)) {
shallow ? push.apply(output, value) : flatten(value, shallow, output);
@@ -449,7 +434,7 @@
return output;
};
// Flatten out an array, either recursively (by default), or just one level.
// Return a completely flattened version of an array.
_.flatten = function(array, shallow) {
return flatten(array, shallow, []);
};
@@ -507,10 +492,20 @@
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = function() {
var length = _.max(_.pluck(arguments, "length").concat(0));
return _.unzip(slice.call(arguments));
};
// The inverse operation to `_.zip`. If given an array of pairs it
// returns an array of the paired elements split into two left and
// right element arrays, if given an array of triples it returns a
// three element array and so on. For example, `_.unzip` given
// `[['a',1],['b',2],['c',3]]` returns the array
// [['a','b','c'],[1,2,3]].
_.unzip = function(list) {
var length = _.max(_.pluck(list, "length").concat(0));
var results = new Array(length);
for (var i = 0; i < length; i++) {
results[i] = _.pluck(arguments, '' + i);
results[i] = _.pluck(list, '' + i);
}
return results;
};
@@ -521,7 +516,7 @@
_.object = function(list, values) {
if (list == null) return {};
var result = {};
for (var i = 0, length = list.length; i < length; i++) {
for (var i = 0, l = list.length; i < l; i++) {
if (values) {
result[list[i]] = values[i];
} else {
@@ -539,17 +534,17 @@
// for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) {
if (array == null) return -1;
var i = 0, length = array.length;
var i = 0, l = array.length;
if (isSorted) {
if (typeof isSorted == 'number') {
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
} else {
i = _.sortedIndex(array, item);
return array[i] === item ? i : -1;
}
}
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
for (; i < length; i++) if (array[i] === item) return i;
for (; i < l; i++) if (array[i] === item) return i;
return -1;
};
@@ -575,11 +570,11 @@
}
step = arguments[2] || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0);
var len = Math.max(Math.ceil((stop - start) / step), 0);
var idx = 0;
var range = new Array(length);
var range = new Array(len);
while(idx < length) {
while(idx < len) {
range[idx++] = start;
start += step;
}
@@ -654,23 +649,19 @@
};
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
// during a given window of time.
_.throttle = function(func, wait, immediate) {
var context, args, result;
var timeout = null;
var previous = 0;
options || (options = {});
var later = function() {
previous = options.leading === false ? 0 : new Date;
previous = new Date;
timeout = null;
result = func.apply(context, args);
};
return function() {
var now = new Date;
if (!previous && options.leading === false) previous = now;
if (!previous && immediate === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
@@ -679,7 +670,7 @@
timeout = null;
previous = now;
result = func.apply(context, args);
} else if (!timeout && options.trailing !== false) {
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
return result;
@@ -691,24 +682,17 @@
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
var result;
var timeout = null;
return function() {
context = this;
args = arguments;
timestamp = new Date();
var context = this, args = arguments;
var later = function() {
var last = (new Date()) - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) result = func.apply(context, args);
}
timeout = null;
if (!immediate) result = func.apply(context, args);
};
var callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(context, args);
return result;
};
@@ -753,6 +737,7 @@
// Returns a function that will only be executed after being called N times.
_.after = function(times, func) {
if (times <= 0) return func();
return function() {
if (--times < 1) {
return func.apply(this, arguments);
@@ -774,33 +759,22 @@
// Retrieve the values of an object's properties.
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = new Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
var values = [];
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
return values;
};
// Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var pairs = new Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
var pairs = [];
for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
return pairs;
};
// Invert the keys and values of an object. The values must be serializable.
_.invert = function(obj) {
var result = {};
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
return result;
};
@@ -917,13 +891,6 @@
// unique nested structures.
if (aStack[length] == a) return bStack[length] == b;
}
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
return false;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
@@ -940,6 +907,13 @@
}
}
} else {
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
return false;
}
// Deep compare objects.
for (var key in a) {
if (_.has(a, key)) {
@@ -1084,7 +1058,8 @@
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;'
"'": '&#x27;',
'/': '&#x2F;'
}
};
entityMap.unescape = _.invert(entityMap.escape);
@@ -1115,7 +1090,7 @@
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
each(_.functions(obj), function(name) {
each(_.functions(obj), function(name){
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];