mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-02 16:17:50 +00:00
Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a82a364c22 | ||
|
|
cc150ff9d2 | ||
|
|
feeb38293d | ||
|
|
5b9271ccfe | ||
|
|
e60bbc2fb7 | ||
|
|
387cc184e6 | ||
|
|
a830ddcb43 | ||
|
|
35fea30191 | ||
|
|
24b672b968 | ||
|
|
de6a3c5ab1 | ||
|
|
260ff6de3e | ||
|
|
7cb37411c9 | ||
|
|
e4e41e5ef8 | ||
|
|
985f4aafca | ||
|
|
0c25dd44b3 | ||
|
|
285f0bc6dd | ||
|
|
07a370fd24 | ||
|
|
95f07ea38a | ||
|
|
2890b92b21 | ||
|
|
8b80c5d0b5 | ||
|
|
04425786a1 | ||
|
|
15b14e12e2 | ||
|
|
b328972c4d | ||
|
|
da3156047f | ||
|
|
f9f08ba54f | ||
|
|
b43684262f | ||
|
|
2120f78bd7 | ||
|
|
2d896f22d6 | ||
|
|
9fa0aebfe9 | ||
|
|
2ddc3af5ff | ||
|
|
fd80e096ea | ||
|
|
fab2d69fce | ||
|
|
83d08e3aba | ||
|
|
bfea6bcacf | ||
|
|
feff34b021 | ||
|
|
79fbade92a | ||
|
|
bf508e453e | ||
|
|
47b51c22fa | ||
|
|
ebd16105f2 | ||
|
|
01fb1a5775 | ||
|
|
b8c2a05db9 | ||
|
|
4087dc5fe4 | ||
|
|
408029e6e0 | ||
|
|
23ff403529 | ||
|
|
be4f81f584 | ||
|
|
361c91e610 | ||
|
|
2aa2ea9675 | ||
|
|
e084225edf | ||
|
|
9ce342205b | ||
|
|
0edf50e00e | ||
|
|
1ea19daad9 | ||
|
|
32b302314e | ||
|
|
ee197e02a2 | ||
|
|
7cd6ffec2a | ||
|
|
0077580838 | ||
|
|
4d85a79fd1 | ||
|
|
a35139bb61 | ||
|
|
f72b833724 | ||
|
|
0e16bac6e2 | ||
|
|
e17564b362 | ||
|
|
90b66eddf5 | ||
|
|
2862a5849f | ||
|
|
7e839231ed | ||
|
|
fa56a4bb73 | ||
|
|
dff950748c | ||
|
|
b7374e3f8e | ||
|
|
4244b92b08 | ||
|
|
4f688028ad | ||
|
|
5a9a18501d | ||
|
|
896b8f7cf1 | ||
|
|
95bd1b014f | ||
|
|
dbdf8642bb | ||
|
|
c3cd9007d2 | ||
|
|
8079fb5bc5 | ||
|
|
80d0b5d4ed | ||
|
|
86bd847bf9 | ||
|
|
943004844a | ||
|
|
4ff12e0426 | ||
|
|
0d7bdb6fa8 | ||
|
|
6d488b6a81 | ||
|
|
f1d0263ffa | ||
|
|
24035caadb | ||
|
|
ed89a3e0f8 | ||
|
|
7088ab89f1 | ||
|
|
d4688bd76b | ||
|
|
befe0fccaf | ||
|
|
a192410498 | ||
|
|
d43ede3a11 | ||
|
|
9848ffb77f | ||
|
|
7487497d1f | ||
|
|
be11c848f4 | ||
|
|
9836b274b9 | ||
|
|
a96d14566f | ||
|
|
1c8cd8c168 | ||
|
|
5f5806a98e | ||
|
|
624b045ac0 | ||
|
|
0f8bae950e | ||
|
|
fcede42903 | ||
|
|
5defe7d975 | ||
|
|
7e79903fe8 | ||
|
|
a2fa52504c | ||
|
|
2629f85e73 | ||
|
|
8577816234 | ||
|
|
e58d47a3b2 | ||
|
|
c9c83ee7e6 | ||
|
|
139693dce6 | ||
|
|
f98193d822 | ||
|
|
8052f1ac9d | ||
|
|
4f78a06993 | ||
|
|
6c4b4b392b | ||
|
|
268fe34238 | ||
|
|
cc620205d6 | ||
|
|
f0d7c97b7b | ||
|
|
660a6e9e4c | ||
|
|
3386c2a7a5 | ||
|
|
9530efb4d4 | ||
|
|
4293515b3d | ||
|
|
61105e0679 | ||
|
|
79a289c7e2 | ||
|
|
46781e7614 | ||
|
|
1f3546a9f6 | ||
|
|
0dc88bb412 |
7
.jamignore
Normal file
7
.jamignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
*.custom.*
|
||||||
|
.*
|
||||||
|
dist/
|
||||||
|
doc/*.php
|
||||||
|
node_modules/
|
||||||
|
perf/*.sh
|
||||||
|
test/*.sh
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
*.custom.*
|
*.custom.*
|
||||||
*.min.*
|
|
||||||
.*
|
.*
|
||||||
dist/
|
dist/
|
||||||
doc/*.php
|
doc/*.php
|
||||||
@@ -11,7 +10,7 @@ test/*-ui.js
|
|||||||
test/*.sh
|
test/*.sh
|
||||||
vendor/backbone/
|
vendor/backbone/
|
||||||
vendor/docdown/
|
vendor/docdown/
|
||||||
vendor/qunit/qunit/*.css
|
|
||||||
vendor/underscore/
|
|
||||||
vendor/requirejs/
|
|
||||||
vendor/firebug-lite/
|
vendor/firebug-lite/
|
||||||
|
vendor/qunit/qunit/*.css
|
||||||
|
vendor/requirejs/
|
||||||
|
vendor/underscore/test/
|
||||||
|
|||||||
215
README.md
215
README.md
@@ -1,14 +1,14 @@
|
|||||||
# Lo-Dash <sup>v0.4.0</sup>
|
# Lo-Dash <sup>v0.5.2</sup>
|
||||||
|
|
||||||
A drop-in replacement for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), that delivers [performance improvements](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#closed-underscorejs-issues), and [additional features](https://github.com/bestiejs/lodash#features).
|
A drop-in replacement<sup>[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer)</sup> for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues-30), and [additional features](https://github.com/bestiejs/lodash#features).
|
||||||
|
|
||||||
Lo-Dash’s performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
|
Lo-Dash’s performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
* [Development source](https://raw.github.com/bestiejs/lodash/v0.4.0/lodash.js)
|
* [Development source](https://raw.github.com/bestiejs/lodash/v0.5.2/lodash.js)
|
||||||
* [Production source](https://raw.github.com/bestiejs/lodash/v0.4.0/lodash.min.js)
|
* [Production source](https://raw.github.com/bestiejs/lodash/v0.5.2/lodash.min.js)
|
||||||
* CDN copies of ≤ [v0.3.2](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.3.2/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
|
* CDN copies of ≤ [v0.5.2](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.5.2/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
|
||||||
* For optimal performance, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
|
* For optimal performance, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
|
||||||
|
|
||||||
## Dive in
|
## Dive in
|
||||||
@@ -24,27 +24,35 @@ For a list of upcoming features, check out our [roadmap](https://github.com/best
|
|||||||
For more information check out these screencasts over Lo-Dash:
|
For more information check out these screencasts over Lo-Dash:
|
||||||
|
|
||||||
* [Introducing Lo-Dash](https://vimeo.com/44154599)
|
* [Introducing Lo-Dash](https://vimeo.com/44154599)
|
||||||
* [Optimizations and custom builds](https://vimeo.com/44154601)
|
* [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
|
||||||
* [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
|
* [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
|
||||||
|
* [Unit testing in Lo-Dash](https://vimeo.com/45865290)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
||||||
* [_.bind](http://lodash.com/docs#bind) supports *"lazy"* binding
|
* [_.bind](http://lodash.com/docs#bind) supports *“lazy”* binding
|
||||||
|
* [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning
|
||||||
|
* [_.countBy](http://lodash.com/docs#countBy) as a compainion function for [_.groupBy](http://lodash.com/docs#groupBy) and [_.sortBy](http://lodash.com/docs#sortBy)
|
||||||
* [_.debounce](http://lodash.com/docs#debounce)’ed functions match [_.throttle](http://lodash.com/docs#throttle)’ed functions’ return value behavior
|
* [_.debounce](http://lodash.com/docs#debounce)’ed functions match [_.throttle](http://lodash.com/docs#throttle)’ed functions’ return value behavior
|
||||||
* [_.forEach](http://lodash.com/docs#forEach) is chainable
|
* [_.drop](http://lodash.com/docs#drop) for the inverse functionality of [_.pick](http://lodash.com/docs#pick)
|
||||||
|
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
|
||||||
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
|
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
|
||||||
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties
|
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties
|
||||||
* [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
|
* [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
|
||||||
* [_.indexOf](http://lodash.com/docs#indexOf) and [_.lastIndexOf](http://lodash.com/docs#lastIndexOf) accept a `fromIndex` argument
|
* [_.indexOf](http://lodash.com/docs#indexOf) and [_.lastIndexOf](http://lodash.com/docs#lastIndexOf) accept a `fromIndex` argument
|
||||||
* [_.partial](http://lodash.com/docs#partial) for more functional fun
|
* [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend)
|
||||||
|
* [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding
|
||||||
|
* [_.sortBy](http://lodash.com/docs#sortBy) performs a [stable](http://en.wikipedia.org/wiki/Sorting_algorithm#Stability) sort
|
||||||
* [_.template](http://lodash.com/docs#template) utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging
|
* [_.template](http://lodash.com/docs#template) utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging
|
||||||
|
* [_.where](http://lodash.com/docs#where) for filtering collections by contained properties
|
||||||
|
* [_.zipObject](http://lodash.com/docs#zipObject) for composing objects
|
||||||
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
|
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
|
||||||
[and more…](http://lodash.com/docs "_.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _sortBy") accept strings
|
[and more…](http://lodash.com/docs "_.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _sortBy") accept strings
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
Lo-Dash has been tested in at least Chrome 5-20, Firefox 1.5-13, IE 6-9, Opera 9.25-12, Safari 3.0.4-5.1.7, Node.js 0.4.8-0.8.2, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC3.
|
Lo-Dash has been tested in at least Chrome 5-21, Firefox 1.5-13, IE 6-9, Opera 9.25-12.01, Safari 3-6, Node.js 0.4.8-0.8.7, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||||
|
|
||||||
## Custom builds
|
## Custom builds
|
||||||
|
|
||||||
@@ -52,47 +60,62 @@ Custom builds make it easy to create lightweight versions of Lo-Dash containing
|
|||||||
We handle all the method dependency and alias mapping for you.
|
We handle all the method dependency and alias mapping for you.
|
||||||
|
|
||||||
* Backbone builds, containing all methods required by Backbone, may be created using the `backbone` modifier argument.
|
* Backbone builds, containing all methods required by Backbone, may be created using the `backbone` modifier argument.
|
||||||
~~~ bash
|
```bash
|
||||||
lodash backbone
|
lodash backbone
|
||||||
~~~
|
```
|
||||||
|
|
||||||
|
* CSP builds, supporting default Content Security Policy restrictions, may be created using the `csp` modifier argument.
|
||||||
|
```bash
|
||||||
|
lodash csp
|
||||||
|
```
|
||||||
|
|
||||||
* Legacy builds, tailored for older browsers without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
|
* Legacy builds, tailored for older browsers without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
|
||||||
~~~ bash
|
```bash
|
||||||
lodash legacy
|
lodash legacy
|
||||||
~~~
|
```
|
||||||
|
|
||||||
* Mobile builds, with IE bug fixes and method compilation removed, may be created using the `mobile` modifier argument.
|
* Mobile builds, with IE < 9 bug fixes and method compilation removed, may be created using the `mobile` modifier argument.
|
||||||
~~~ bash
|
```bash
|
||||||
lodash mobile
|
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, containing only methods included in Underscore, may be created using the `underscore` modifier argument.
|
||||||
|
```bash
|
||||||
|
lodash underscore
|
||||||
|
```
|
||||||
|
|
||||||
Custom builds may be created in three ways:
|
Custom builds may be created in three ways:
|
||||||
|
|
||||||
1. Use the `category` argument to pass the categories of methods to include in the build.<br>
|
1. Use the `category` argument to pass the categories of methods to include in the build.<br>
|
||||||
Valid categories are *"arrays"*, *"chaining"*, *"collections"*, *"functions"*, *"objects"*, and *"utilities"*.
|
Valid categories are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
|
||||||
~~~ bash
|
```bash
|
||||||
lodash category=collections,functions
|
lodash category=collections,functions
|
||||||
lodash category="collections, functions"
|
lodash category="collections, functions"
|
||||||
~~~
|
```
|
||||||
|
|
||||||
2. Use the `include` argument to pass the names of methods to include in the build.
|
2. Use the `exclude` argument to pass the names of methods to exclude from the build.
|
||||||
~~~ bash
|
```bash
|
||||||
lodash include=each,filter,map
|
|
||||||
lodash include="each, filter, map"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
3. Use the `exclude` argument to pass the names of methods to exclude from the build.
|
|
||||||
~~~ bash
|
|
||||||
lodash exclude=union,uniq,zip
|
lodash exclude=union,uniq,zip
|
||||||
lodash exclude="union, uniq, zip"
|
lodash exclude="union, uniq, zip"
|
||||||
~~~
|
```
|
||||||
|
|
||||||
All arguments, except `include` with `exclude` and `mobile` with `legacy`, may be combined.
|
3. Use the `include` argument to pass the names of methods to include in the build.
|
||||||
|
```bash
|
||||||
|
lodash include=each,filter,map
|
||||||
|
lodash include="each, filter, map"
|
||||||
|
```
|
||||||
|
|
||||||
~~~ bash
|
All arguments, except `backbone` with `underscore`, `exclude` with `include`, and `legacy` with `csp`/`mobile`, may be combined.
|
||||||
lodash backbone mobile category=functions include=pick,uniq
|
|
||||||
|
```bash
|
||||||
lodash backbone legacy category=utilities exclude=first,last
|
lodash backbone legacy category=utilities exclude=first,last
|
||||||
~~~
|
lodash underscore mobile strict category=functions include=pick,uniq
|
||||||
|
```
|
||||||
|
|
||||||
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
||||||
|
|
||||||
@@ -102,38 +125,38 @@ Custom builds are saved to `lodash.custom.js` and `lodash.custom.min.js`.
|
|||||||
|
|
||||||
In browsers:
|
In browsers:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<script src="lodash.js"></script>
|
<script src="lodash.js"></script>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Using [npm](http://npmjs.org/):
|
Using [npm](http://npmjs.org/):
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install lodash
|
npm install lodash
|
||||||
npm install -g lodash
|
npm install -g lodash
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var _ = require('lodash')._;
|
var _ = require('lodash')._;
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Rhino](http://www.mozilla.org/rhino/):
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
load('lodash.js');
|
load('lodash.js');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
require({
|
require({
|
||||||
'paths': {
|
'paths': {
|
||||||
'underscore': 'path/to/lodash'
|
'underscore': 'path/to/lodash'
|
||||||
@@ -142,33 +165,42 @@ require({
|
|||||||
['underscore'], function(_) {
|
['underscore'], function(_) {
|
||||||
console.log(_.VERSION);
|
console.log(_.VERSION);
|
||||||
});
|
});
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Closed Underscore.js issues <sup>(20+)</sup>
|
## Resolved Underscore.js issues <sup>(30+)</sup>
|
||||||
|
|
||||||
* Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L306-312)]
|
* Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L551-557)]
|
||||||
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L257-263), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L607-621), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L840-843)]
|
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L499-509)]
|
||||||
* Ensure *"Arrays"* methods allow falsey `array` arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L908-947)]
|
* Ensure *“Arrays”*, “Collections”, and “Objects” methods don’t error when passed falsey arguments [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1558-1593)]
|
||||||
* Ensure *"Collections"* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L265-283), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L623-640), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L845-848)]
|
* Ensure *“Collections”* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L511-529)]
|
||||||
* Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L737-744)]
|
* Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1299-1302)]
|
||||||
* Fix cross-browser object iteration bugs [[#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L195-207), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L317-342), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L438-449), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L457-459), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L477-497), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L667-669)]
|
* Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L562-587)]
|
||||||
* Handle arrays with `undefined` values correctly in IE < 9 [[#601](https://github.com/documentcloud/underscore/issues/601)]
|
* Handle arrays with `undefined` values correctly in IE < 9 [[#601](https://github.com/documentcloud/underscore/issues/601)]
|
||||||
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L86-92)]
|
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L117-123)]
|
||||||
* Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L70-84)]
|
* Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L101-115)]
|
||||||
* `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L104-107)]
|
* `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L135-138)]
|
||||||
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L138-147)]
|
* `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L205-220)]
|
||||||
* `_.escape` should return an empty string when passed `null` or `undefined` [[#407](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L176-179)]
|
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L275-284)]
|
||||||
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L252-255)]
|
* `_.escape` should return an empty string when passed `null` or `undefined` [[#427](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L375-378)]
|
||||||
* `_.groupBy` should add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L357-364)]
|
* `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L952-974)]
|
||||||
* `_isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L467-469)]
|
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L494-497)]
|
||||||
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L591-605)]
|
* `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L589-608)]
|
||||||
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L650-652)]
|
* `_.groupBy` should add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L623-630)]
|
||||||
* `_.size` shouldn't error on falsey values [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L654-661)]
|
* `_.isElement` should use strict equality for its duck type check [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L704-713)]
|
||||||
* `_.size` should work with `arguments` objects cross-browser [[#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L663-665)]
|
* `_.isEmpty` and `_.size` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L740-745)]
|
||||||
* `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L707-716)]
|
* `_.isEqual` should return `true` for like-objects from different documents [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L781-801)]
|
||||||
* `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L731-735)]
|
* `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L809-821)]
|
||||||
* `_.throttle` should work when called in a tight loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L791-801)]
|
* `_.isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L829-831)]
|
||||||
* `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.0/test/test.js#L870-872)]
|
* `_.keys` and `_.size` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L885-887)]
|
||||||
|
* `_.once` should free the given function for garbage collection [[#693](https://github.com/documentcloud/underscore/pull/693)]
|
||||||
|
* `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1110-1113)]
|
||||||
|
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1121-1135)]
|
||||||
|
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1179-1181)]
|
||||||
|
* `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1269-1278)]
|
||||||
|
* `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1293-1297)]
|
||||||
|
* `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1389-1399)]
|
||||||
|
* `_.toArray` uses custom `toArray` methods of arrays and strings [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1426-1434)]
|
||||||
|
* `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.5.2/test/test.js#L1520-1522)]
|
||||||
|
|
||||||
## Optimized methods <sup>(50+)</sup>
|
## Optimized methods <sup>(50+)</sup>
|
||||||
|
|
||||||
@@ -196,7 +228,6 @@ require({
|
|||||||
* `_.isArguments`
|
* `_.isArguments`
|
||||||
* `_.isDate`
|
* `_.isDate`
|
||||||
* `_.isEmpty`
|
* `_.isEmpty`
|
||||||
* `_.isEqual`
|
|
||||||
* `_.isFinite`
|
* `_.isFinite`
|
||||||
* `_.isFunction`
|
* `_.isFunction`
|
||||||
* `_.isObject`
|
* `_.isObject`
|
||||||
@@ -233,27 +264,41 @@ require({
|
|||||||
|
|
||||||
## Release Notes
|
## Release Notes
|
||||||
|
|
||||||
### <sup>v0.4.0</sup>
|
### <sup>v0.5.2</sup>
|
||||||
|
|
||||||
* Added `bin` and `scripts` entries to package.json
|
* Ensured `_.isElement` uses strict equality for its duck type check
|
||||||
* Added `legacy` build option
|
* Ensured `_.isObject` returns a boolean value
|
||||||
* Added cross-browser support for passing strings to *"Collections"* methods
|
* Ensured `_.template` and *“Objects”* methods don’t error when passed falsey arguments
|
||||||
* Added `_.zipObject`
|
* Made `_.template` generate less unused code in compiled templates
|
||||||
* Leveraged `_.indexOf`'s `fromIndex` in `_.difference` and `_.without`
|
|
||||||
* Optimized compiled templates
|
### <sup>v0.5.1</sup>
|
||||||
* Optimized inlining the `iteratorTemplate` for builds
|
|
||||||
* Optimized object iteration for *"Collections"* methods
|
* Ensured `_.bind` correctly appends array arguments to partially applied arguments in older browsers
|
||||||
* Optimized partially applied `_.bind` in V8
|
|
||||||
* Made compiled templates more debuggable
|
### <sup>v0.5.0</sup>
|
||||||
* Made `_.size` work with falsey values and consistent cross-browser with `arguments` objects
|
|
||||||
* Moved `_.groupBy` and `_.sortBy` back to the *"Collections"* category
|
* Added [_.countBy](http://lodash.com/docs#countBy), [_.drop](http://lodash.com/docs#drop), [_.merge](http://lodash.com/docs#merge), and [_.where](http://lodash.com/docs#where)
|
||||||
* Removed `arguments` object from `_.range`
|
* Added `csp` *(Content Security Policy)* and `underscore` build options
|
||||||
|
* Added `deep` cloning support to `_.clone`
|
||||||
|
* Added [Jam](http://jamjs.org/) package support
|
||||||
|
* Added support for exiting `_.forEach`, `_.forIn`, and `_.forOwn` early by returning `false` in the `callback`
|
||||||
|
* Added support for jQuery/MooTools DOM query collections to `_.isEmpty` and `_.size`
|
||||||
|
* Ensured development build works with IE conditional compilation enabled
|
||||||
|
* Ensured `_.clone` doesn’t clone functions, DOM nodes, `arguments` objects, and objects created by constructors other than `Object`
|
||||||
|
* Ensured `_.filter`’s `callback` can’t modify result values
|
||||||
|
* Ensured `_.isEmpty`, `_.isEquals`, and `_.size` support `arguments` objects
|
||||||
|
* Ensured `_.isEqual` doesn’t inspect DOM nodes, works with objects from other documents, and calls custom `isEqual` methods before checking strict equality
|
||||||
|
* Ensured `_.once` frees the given function for garbage collection
|
||||||
|
* Ensured `_.sortBy` performs a stable sort
|
||||||
|
* Ensured `reEvaluateDelimiter` is assigned when `_.templateSettings.evaluate` is undefined
|
||||||
|
* Made `_.range` coerce arguments to numbers
|
||||||
|
* Optimized `_.isFunction`
|
||||||
|
|
||||||
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
|
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
|
||||||
|
|
||||||
## BestieJS
|
## 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.
|
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
|
## Author
|
||||||
|
|
||||||
|
|||||||
511
build.js
511
build.js
@@ -11,14 +11,29 @@
|
|||||||
/** The current working directory */
|
/** The current working directory */
|
||||||
var cwd = process.cwd();
|
var cwd = process.cwd();
|
||||||
|
|
||||||
/** Flag used to specify a backbone build */
|
/** Flag used to specify a Backbone build */
|
||||||
var isBackbone = process.argv.indexOf('backbone') > -1;
|
var isBackbone = process.argv.indexOf('backbone') > -1;
|
||||||
|
|
||||||
|
/** Flag used to specify a Content Security Policy build */
|
||||||
|
var isCSP = process.argv.indexOf('csp') > -1 || process.argv.indexOf('CSP') > -1;
|
||||||
|
|
||||||
/** Flag used to specify a legacy build */
|
/** Flag used to specify a legacy build */
|
||||||
var isLegacy = process.argv.indexOf('legacy') > -1;
|
var isLegacy = process.argv.indexOf('legacy') > -1;
|
||||||
|
|
||||||
/** Flag used to specify a mobile build */
|
/** Flag used to specify a mobile build */
|
||||||
var isMobile = !isLegacy && process.argv.indexOf('mobile') > -1;
|
var isMobile = !isLegacy && (isCSP || process.argv.indexOf('mobile') > -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
|
||||||
|
* constructed using the "use strict" directive.
|
||||||
|
*/
|
||||||
|
var isStrict = process.argv.indexOf('strict') > -1;
|
||||||
|
|
||||||
|
/** Flag used to specify an Underscore build */
|
||||||
|
var isUnderscore = process.argv.indexOf('underscore') > -1;
|
||||||
|
|
||||||
|
/** Flag used to specify if the build should include the "use strict" directive */
|
||||||
|
var useStrict = isStrict || !(isLegacy || isMobile);
|
||||||
|
|
||||||
/** Shortcut used to convert array-like objects to arrays */
|
/** Shortcut used to convert array-like objects to arrays */
|
||||||
var slice = [].slice;
|
var slice = [].slice;
|
||||||
@@ -30,7 +45,16 @@
|
|||||||
var lodash = (function() {
|
var lodash = (function() {
|
||||||
var sandbox = {};
|
var sandbox = {};
|
||||||
|
|
||||||
|
if (isStrict) {
|
||||||
|
source = setUseStrictOption(source, true);
|
||||||
|
}
|
||||||
|
else if (!useStrict) {
|
||||||
|
source = removeUseStrictDirective(source);
|
||||||
|
source = setUseStrictOption(source, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (isLegacy) {
|
if (isLegacy) {
|
||||||
|
source = replaceVar(source, 'noArgsClass', 'true');
|
||||||
['isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
|
['isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
|
||||||
source = replaceVar(source, varName, 'false');
|
source = replaceVar(source, varName, 'false');
|
||||||
});
|
});
|
||||||
@@ -126,29 +150,31 @@
|
|||||||
/** Used to track function dependencies */
|
/** Used to track function dependencies */
|
||||||
var dependencyMap = {
|
var dependencyMap = {
|
||||||
'after': [],
|
'after': [],
|
||||||
'bind': [],
|
'bind': ['isFunction'],
|
||||||
'bindAll': ['bind', 'functions'],
|
'bindAll': ['bind', 'isFunction'],
|
||||||
'chain': ['mixin'],
|
'chain': ['mixin'],
|
||||||
'clone': ['extend', 'isArray'],
|
'clone': ['extend', 'forIn', 'forOwn', 'isArguments', 'isFunction'],
|
||||||
'compact': [],
|
'compact': [],
|
||||||
'compose': [],
|
'compose': [],
|
||||||
'contains': [],
|
'contains': [],
|
||||||
|
'countBy': [],
|
||||||
'debounce': [],
|
'debounce': [],
|
||||||
'defaults': [],
|
'defaults': ['isArguments'],
|
||||||
'defer': [],
|
'defer': [],
|
||||||
'delay': [],
|
'delay': [],
|
||||||
'difference': ['indexOf'],
|
'difference': ['indexOf'],
|
||||||
|
'drop': ['indexOf', 'isArguments'],
|
||||||
'escape': [],
|
'escape': [],
|
||||||
'every': ['identity'],
|
'every': ['identity'],
|
||||||
'extend': [],
|
'extend': ['isArguments'],
|
||||||
'filter': ['identity'],
|
'filter': ['identity'],
|
||||||
'find': [],
|
'find': [],
|
||||||
'first': [],
|
'first': [],
|
||||||
'flatten': ['isArray'],
|
'flatten': ['isArray'],
|
||||||
'forEach': [],
|
'forEach': [],
|
||||||
'forIn': [],
|
'forIn': ['isArguments'],
|
||||||
'forOwn': [],
|
'forOwn': ['isArguments'],
|
||||||
'functions': [],
|
'functions': ['isArguments', 'isFunction'],
|
||||||
'groupBy': [],
|
'groupBy': [],
|
||||||
'has': [],
|
'has': [],
|
||||||
'identity': [],
|
'identity': [],
|
||||||
@@ -161,8 +187,8 @@
|
|||||||
'isBoolean': [],
|
'isBoolean': [],
|
||||||
'isDate': [],
|
'isDate': [],
|
||||||
'isElement': [],
|
'isElement': [],
|
||||||
'isEmpty': [],
|
'isEmpty': ['isArguments', 'isFunction'],
|
||||||
'isEqual': [],
|
'isEqual': ['isArguments', 'isFunction'],
|
||||||
'isFinite': [],
|
'isFinite': [],
|
||||||
'isFunction': [],
|
'isFunction': [],
|
||||||
'isNaN': [],
|
'isNaN': [],
|
||||||
@@ -172,12 +198,13 @@
|
|||||||
'isRegExp': [],
|
'isRegExp': [],
|
||||||
'isString': [],
|
'isString': [],
|
||||||
'isUndefined': [],
|
'isUndefined': [],
|
||||||
'keys': [],
|
'keys': ['isArguments'],
|
||||||
'last': [],
|
'last': [],
|
||||||
'lastIndexOf': [],
|
'lastIndexOf': [],
|
||||||
'map': ['identity'],
|
'map': ['identity'],
|
||||||
'max': [],
|
'max': [],
|
||||||
'memoize': [],
|
'memoize': [],
|
||||||
|
'merge': ['isArguments', 'isArray', 'forIn'],
|
||||||
'min': [],
|
'min': [],
|
||||||
'mixin': ['forEach', 'functions'],
|
'mixin': ['forEach', 'functions'],
|
||||||
'noConflict': [],
|
'noConflict': [],
|
||||||
@@ -190,9 +217,9 @@
|
|||||||
'reduceRight': ['keys'],
|
'reduceRight': ['keys'],
|
||||||
'reject': ['identity'],
|
'reject': ['identity'],
|
||||||
'rest': [],
|
'rest': [],
|
||||||
'result': [],
|
'result': ['isFunction'],
|
||||||
'shuffle': [],
|
'shuffle': [],
|
||||||
'size': ['keys'],
|
'size': ['isArguments', 'isFunction', 'keys'],
|
||||||
'some': ['identity'],
|
'some': ['identity'],
|
||||||
'sortBy': [],
|
'sortBy': [],
|
||||||
'sortedIndex': ['bind'],
|
'sortedIndex': ['bind'],
|
||||||
@@ -200,11 +227,12 @@
|
|||||||
'template': ['escape'],
|
'template': ['escape'],
|
||||||
'throttle': [],
|
'throttle': [],
|
||||||
'times': [],
|
'times': [],
|
||||||
'toArray': ['values'],
|
'toArray': ['isFunction', 'values'],
|
||||||
'union': ['indexOf'],
|
'union': ['indexOf'],
|
||||||
'uniq': ['identity', 'indexOf'],
|
'uniq': ['identity', 'indexOf'],
|
||||||
'uniqueId': [],
|
'uniqueId': [],
|
||||||
'values': [],
|
'values': ['isArguments'],
|
||||||
|
'where': ['forIn'],
|
||||||
'without': ['indexOf'],
|
'without': ['indexOf'],
|
||||||
'wrap': [],
|
'wrap': [],
|
||||||
'zip': ['max', 'pluck'],
|
'zip': ['max', 'pluck'],
|
||||||
@@ -224,20 +252,32 @@
|
|||||||
'inLoop',
|
'inLoop',
|
||||||
'init',
|
'init',
|
||||||
'isKeysFast',
|
'isKeysFast',
|
||||||
'iteratee',
|
|
||||||
'object',
|
'object',
|
||||||
'objectBranch',
|
'objectBranch',
|
||||||
|
'noArgsEnum',
|
||||||
'noCharByIndex',
|
'noCharByIndex',
|
||||||
'shadowed',
|
'shadowed',
|
||||||
'top',
|
'top',
|
||||||
'useHas'
|
'useHas',
|
||||||
|
'useStrict'
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Collections of method names */
|
/** Collections of method names */
|
||||||
var excludeMethods,
|
var excludeMethods = [],
|
||||||
includeMethods,
|
includeMethods = [],
|
||||||
allMethods = Object.keys(dependencyMap);
|
allMethods = Object.keys(dependencyMap);
|
||||||
|
|
||||||
|
var underscoreMethods = lodash.without.apply(lodash, [allMethods].concat([
|
||||||
|
'countBy',
|
||||||
|
'drop',
|
||||||
|
'forIn',
|
||||||
|
'forOwn',
|
||||||
|
'merge',
|
||||||
|
'partial',
|
||||||
|
'where',
|
||||||
|
'zipObject'
|
||||||
|
]));
|
||||||
|
|
||||||
/** Used to specify whether filtering is for exclusion or inclusion */
|
/** Used to specify whether filtering is for exclusion or inclusion */
|
||||||
var filterType = process.argv.reduce(function(result, value) {
|
var filterType = process.argv.reduce(function(result, value) {
|
||||||
if (result) {
|
if (result) {
|
||||||
@@ -261,6 +301,37 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the help message to the console.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function displayHelp() {
|
||||||
|
console.log([
|
||||||
|
'',
|
||||||
|
' Commands:',
|
||||||
|
'',
|
||||||
|
' lodash backbone Build containing all methods required by Backbone',
|
||||||
|
' lodash csp Build supporting default Content Security Policy restrictions',
|
||||||
|
' lodash legacy Build tailored for older browsers without ES5 support',
|
||||||
|
' lodash mobile Build with IE < 9 bug fixes and method compilation removed',
|
||||||
|
' lodash strict Build with `_.bindAll`, `_.defaults`, and `_.extend` in strict mode',
|
||||||
|
' lodash underscore Build containing only methods included in Underscore',
|
||||||
|
' lodash category=... Comma separated categories of methods to include in the build',
|
||||||
|
' lodash exclude=... Comma separated names of methods to exclude from the build',
|
||||||
|
' lodash include=... Comma separated names of methods to include in the build',
|
||||||
|
'',
|
||||||
|
' All arguments, except `backbone` with `underscore`, `exclude` with `include`,',
|
||||||
|
' and `legacy` with `csp`/`mobile`, may be combined.',
|
||||||
|
'',
|
||||||
|
' Options:',
|
||||||
|
'',
|
||||||
|
' -h, --help Display help information',
|
||||||
|
' -V, --version Output current version of Lo-Dash',
|
||||||
|
''
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the aliases associated with a given function name.
|
* Gets the aliases associated with a given function name.
|
||||||
*
|
*
|
||||||
@@ -272,6 +343,17 @@
|
|||||||
return realToAliasMap[funcName] || [];
|
return realToAliasMap[funcName] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Lo-Dash method assignments snippet from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to inspect.
|
||||||
|
* @returns {String} Returns the method assignments snippet.
|
||||||
|
*/
|
||||||
|
function getMethodAssignments(source) {
|
||||||
|
return (source.match(/lodash\.VERSION *= *[\s\S]+?\/\*-+\*\/\n/) || [''])[0];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an array of depenants for a function by a given name.
|
* Gets an array of depenants for a function by a given name.
|
||||||
*
|
*
|
||||||
@@ -340,7 +422,7 @@
|
|||||||
* @returns {String} Returns the `isArguments` fallback snippet.
|
* @returns {String} Returns the `isArguments` fallback snippet.
|
||||||
*/
|
*/
|
||||||
function getIsArgumentsFallback(source) {
|
function getIsArgumentsFallback(source) {
|
||||||
return (source.match(/(?:\s*\/\/.*)*\s*if *\(!(?:lodash\.)?isArguments[^)]+\)[\s\S]+?};\s*}/) || [''])[0];
|
return (source.match(/(?:\s*\/\/.*)*\s*if *\(noArgsClass[\s\S]+?};\s*}/) || [''])[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,10 +487,14 @@
|
|||||||
* @returns {String} Returns the modified source.
|
* @returns {String} Returns the modified source.
|
||||||
*/
|
*/
|
||||||
function removeFromCreateIterator(source, refName) {
|
function removeFromCreateIterator(source, refName) {
|
||||||
var snippet = matchFunction(source, 'createIterator').match(/Function\([\s\S]+$/)[0],
|
var snippet = matchFunction(source, 'createIterator');
|
||||||
modified = snippet.replace(RegExp('\\b' + refName + '\\b,? *', 'g'), '');
|
if (snippet) {
|
||||||
|
// clip the snippet at the `factory` assignment
|
||||||
return source.replace(snippet, modified);
|
snippet = snippet.match(/Function\([\s\S]+$/)[0];
|
||||||
|
var modified = snippet.replace(RegExp('\\b' + refName + '\\b,? *', 'g'), '');
|
||||||
|
source = source.replace(snippet, modified);
|
||||||
|
}
|
||||||
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,7 +518,7 @@
|
|||||||
source = source.replace(matchFunction(source, funcName), '');
|
source = source.replace(matchFunction(source, funcName), '');
|
||||||
|
|
||||||
// grab the method assignments snippet
|
// grab the method assignments snippet
|
||||||
snippet = source.match(/lodash\.VERSION *= *[\s\S]+?\/\*-+\*\/\n/)[0];
|
snippet = getMethodAssignments(source);
|
||||||
|
|
||||||
// remove assignment and aliases
|
// remove assignment and aliases
|
||||||
modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
|
modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) {
|
||||||
@@ -445,6 +531,17 @@
|
|||||||
return removeFromCreateIterator(source, funcName);
|
return removeFromCreateIterator(source, funcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the `_.isFunction` fallback from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @returns {String} Returns the source with the `isFunction` fallback removed.
|
||||||
|
*/
|
||||||
|
function removeIsFunctionFallback(source) {
|
||||||
|
return source.replace(/(?:\s*\/\/.*)*\s*if *\(isFunction\(\/x\/[\s\S]+?};\s*}/, '');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the `_.isArguments` fallback from `source`.
|
* Removes the `_.isArguments` fallback from `source`.
|
||||||
*
|
*
|
||||||
@@ -465,14 +562,57 @@
|
|||||||
*/
|
*/
|
||||||
function removeKeysOptimization(source) {
|
function removeKeysOptimization(source) {
|
||||||
return removeVar(source, 'isKeysFast')
|
return removeVar(source, 'isKeysFast')
|
||||||
|
// remove optimized branch in `iteratorTemplate`
|
||||||
|
.replace(/(?: *\/\/.*\n)*\s*'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2')
|
||||||
// remove `isKeysFast` from `beforeLoop.object` of `mapIteratorOptions`
|
// remove `isKeysFast` from `beforeLoop.object` of `mapIteratorOptions`
|
||||||
.replace(/=\s*'\s*\+\s*\(isKeysFast.+/, "= []'")
|
.replace(/=\s*'\s*\+\s*\(isKeysFast.+/, "= []'")
|
||||||
// remove `isKeysFast` from `inLoop.object` of `mapIteratorOptions`, `invoke`, `pluck`, and `sortBy`
|
// remove `isKeysFast` from `inLoop.object` of `mapIteratorOptions`, `invoke`, `pluck`, and `sortBy`
|
||||||
.replace(/'\s*\+\s*\(isKeysFast[^)]+?\)\s*\+\s*'/g, '.push')
|
.replace(/'\s*\+\s*\(isKeysFast[^)]+?\)\s*\+\s*'/g, '.push')
|
||||||
// remove data object property assignment in `createIterator`
|
// remove data object property assignment in `createIterator`
|
||||||
.replace(/\s*.+?\.isKeysFast *=.+/, '')
|
.replace(/\s*.+?\.isKeysFast *=.+/, '');
|
||||||
// remove optimized branch in `iteratorTemplate`
|
}
|
||||||
.replace(/(?: *\/\/.*\n)*\s*'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2');
|
|
||||||
|
/**
|
||||||
|
* Removes all `noArgsClass` references from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @returns {String} Returns the modified source.
|
||||||
|
*/
|
||||||
|
function removeNoArgsClass(source) {
|
||||||
|
return removeVar(source, 'noArgsClass')
|
||||||
|
// remove `noArgsClass` from `_.clone`, `_.isEqual`, and `_.size`
|
||||||
|
.replace(/ *\|\| *\(noArgsClass *&&[^)]+?\)\)/g, '')
|
||||||
|
// remove `noArgsClass` from `_.isEqual`
|
||||||
|
.replace(/if *\(noArgsClass[^}]+?}\n/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all `noNodeClass` references from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @returns {String} Returns the modified source.
|
||||||
|
*/
|
||||||
|
function removeNoNodeClass(source) {
|
||||||
|
return source
|
||||||
|
// remove `noNodeClass` assignment
|
||||||
|
.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var noNodeClass[\s\S]+?catch[^}]+}\n/, '')
|
||||||
|
// remove `noNodeClass` from `isPlainObject`
|
||||||
|
.replace(/\(!noNodeClass *\|\|[\s\S]+?\)\) *&&/, '')
|
||||||
|
// remove `noNodeClass` from `_.isEqual`
|
||||||
|
.replace(/ *\|\| *\(noNodeClass *&&[\s\S]+?\)\)\)/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the "use strict" directive from `source`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @returns {String} Returns the modified source.
|
||||||
|
*/
|
||||||
|
function removeUseStrictDirective(source) {
|
||||||
|
return source.replace(/(["'])use strict\1;( *\n)?/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -503,6 +643,9 @@
|
|||||||
// remove a variable at the end of a variable declaration list
|
// remove a variable at the end of a variable declaration list
|
||||||
source = source.replace(RegExp(',\\s*' + varName + ' *=.+?;'), ';');
|
source = source.replace(RegExp(',\\s*' + varName + ' *=.+?;'), ';');
|
||||||
|
|
||||||
|
// remove variable reference from `arrayLikeClasses` and `cloneableClasses` assignments
|
||||||
|
source = source.replace(RegExp('(?:arrayLikeClasses|cloneableClasses)\\[' + varName + '\\] *= *(?:false|true)?', 'g'), '');
|
||||||
|
|
||||||
return removeFromCreateIterator(source, varName);
|
return removeFromCreateIterator(source, varName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,27 +674,104 @@
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hard-codes the `useStrict` template option value for `iteratorTemplate`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to process.
|
||||||
|
* @param {Boolean} value The value to set.
|
||||||
|
* @returns {String} Returns the modified source.
|
||||||
|
*/
|
||||||
|
function setUseStrictOption(source, value) {
|
||||||
|
return source
|
||||||
|
// replace `useStrict` branch in `value` with hard-coded option
|
||||||
|
.replace(/(?: *\/\/.*\n)*(\s*)' *<% *if *\(useStrict\).+/, value ? "$1'\\'use strict\\';\\n' +" : '')
|
||||||
|
// remove `useStrict` from iterator options
|
||||||
|
.replace(/ *'useStrict': *false,\n/g, '')
|
||||||
|
// remove `useStrict` data object property assignment in `createIterator`
|
||||||
|
.replace(/\s*.+?\.useStrict *=.+/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes `source` to a file with the given `filename` to the current
|
||||||
|
* working directory.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} source The source to write.
|
||||||
|
* @param {String} filename The name of the file.
|
||||||
|
*/
|
||||||
|
function writeFile(source, filename) {
|
||||||
|
// correct overly aggressive Closure Compiler minification
|
||||||
|
source = source.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}');
|
||||||
|
|
||||||
|
// re-remove "use strict" added by the minifier
|
||||||
|
if (!useStrict) {
|
||||||
|
source = removeUseStrictDirective(source);
|
||||||
|
}
|
||||||
|
fs.writeFileSync(path.join(cwd, filename), source);
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// Backbone build
|
// display help message
|
||||||
if (isBackbone) {
|
if (lodash.find(process.argv, function(arg) {
|
||||||
|
return /^(?:-h|--help)$/.test(arg);
|
||||||
|
})) {
|
||||||
|
displayHelp();
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// display `lodash.VERSION`
|
||||||
|
if (lodash.find(process.argv, function(arg) {
|
||||||
|
return /^(?:-V|--version)$/.test(arg);
|
||||||
|
})) {
|
||||||
|
console.log(lodash.VERSION);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// don't expose `_.forIn` or `_.forOwn` if `isUnderscore` is `true` unless
|
||||||
|
// requested by `include`
|
||||||
|
if (isUnderscore) {
|
||||||
|
if (includeMethods.indexOf('forIn') == -1) {
|
||||||
|
source = source.replace(/ *lodash\.forIn *=.+\n/, '');
|
||||||
|
}
|
||||||
|
if (includeMethods.indexOf('forOwn') == -1) {
|
||||||
|
source = source.replace(/ *lodash\.forOwn *=.+\n/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add methods required by Backbone or Underscore
|
||||||
|
[
|
||||||
|
{ 'flag': isBackbone, 'methodNames': backboneDependencies },
|
||||||
|
{ 'flag': isUnderscore, 'methodNames': underscoreMethods }
|
||||||
|
]
|
||||||
|
.some(function(data) {
|
||||||
|
var flag = data.flag,
|
||||||
|
methodNames = data.methodNames;
|
||||||
|
|
||||||
|
if (!flag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// add any additional sub-dependencies
|
// add any additional sub-dependencies
|
||||||
backboneDependencies = getDependencies(backboneDependencies);
|
methodNames = getDependencies(methodNames);
|
||||||
|
|
||||||
if (filterType == 'exclude') {
|
if (filterType == 'exclude') {
|
||||||
// remove excluded methods from `backboneDependencies`
|
// remove excluded methods from `methodNames`
|
||||||
includeMethods = lodash.without.apply(lodash, [backboneDependencies].concat(excludeMethods));
|
includeMethods = lodash.without.apply(lodash, [methodNames].concat(excludeMethods));
|
||||||
}
|
}
|
||||||
else if (filterType) {
|
else if (filterType) {
|
||||||
// merge backbone dependencies into `includeMethods`
|
// merge `methodNames` into `includeMethods`
|
||||||
includeMethods = lodash.union(includeMethods, backboneDependencies);
|
includeMethods = lodash.union(includeMethods, methodNames);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// include only the Backbone dependencies
|
// include only the `methodNames`
|
||||||
includeMethods = backboneDependencies;
|
includeMethods = methodNames;
|
||||||
}
|
}
|
||||||
filterType = 'include';
|
filterType = 'include';
|
||||||
}
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -612,67 +832,22 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove associated functions, variables, and code snippets
|
// remove `isArguments` fallback before `isArguments` is transformed by
|
||||||
|
// other parts of the build process
|
||||||
if (isRemoved(source, 'isArguments')) {
|
if (isRemoved(source, 'isArguments')) {
|
||||||
source = removeIsArgumentsFallback(source);
|
source = removeIsArgumentsFallback(source);
|
||||||
}
|
}
|
||||||
if (isRemoved(source, 'mixin')) {
|
|
||||||
// remove `LoDash` constructor
|
|
||||||
source = removeFunction(source, 'LoDash');
|
|
||||||
// remove `LoDash` calls
|
|
||||||
source = source.replace(/(?:new +LoDash(?!\()|(?:new +)?LoDash\([^)]*\));?/g, '');
|
|
||||||
// remove `LoDash.prototype` additions
|
|
||||||
source = source.replace(/(?:\s*\/\/.*)*\s*LoDash.prototype *=[\s\S]+?\/\*-+\*\//, '');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'sortBy')) {
|
|
||||||
source = removeFunction(source, 'compareAscending');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'template')) {
|
|
||||||
// remove `templateSettings` assignment
|
|
||||||
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'isArray', 'isEmpty', 'isEqual', 'size')) {
|
|
||||||
source = removeVar(source, 'arrayClass');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'bind', 'functions', 'groupBy', 'invoke', 'isEqual', 'isFunction', 'result', 'sortBy', 'toArray')) {
|
|
||||||
source = removeVar(source, 'funcClass');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'bind')) {
|
|
||||||
source = removeVar(source, 'nativeBind');
|
|
||||||
source = removeVar(source, 'isBindFast');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'isArray')) {
|
|
||||||
source = removeVar(source, 'nativeIsArray');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'keys')) {
|
|
||||||
source = removeFunction(source, 'shimKeys');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'clone', 'isObject', 'keys')) {
|
|
||||||
source = removeVar(source, 'objectTypes');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'bind', 'isArray', 'keys')) {
|
|
||||||
source = removeVar(source, 'reNative');
|
|
||||||
}
|
|
||||||
if (isRemoved(source, 'isEmpty', 'isEqual', 'isString', 'size')) {
|
|
||||||
source = removeVar(source, 'stringClass');
|
|
||||||
}
|
|
||||||
|
|
||||||
// consolidate consecutive horizontal rule comment separators
|
|
||||||
source = source.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
|
|
||||||
return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
|
|
||||||
});
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// simplify template snippets
|
// simplify template snippets by removing unnecessary brackets
|
||||||
source = source.replace(
|
source = source.replace(
|
||||||
RegExp(
|
RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *([,\\n])", 'g'), "$1'$2"
|
||||||
"'else if \\(thisArg\\) \\{\\\\n' \\+\\s*" +
|
);
|
||||||
"' callback = iteratorBind\\(callback, thisArg\\)\\\\n' \\+\\s*" +
|
|
||||||
"'}'"
|
source = source.replace(
|
||||||
, 'g'),
|
RegExp("{(\\\\n' *\\+\\s*.*?\\+\\n\\s*' *)}(?:\\\\n)?' *\\+", 'g'), "$1;\\n'+"
|
||||||
"'else if (thisArg) callback = iteratorBind(callback, thisArg)'"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -687,32 +862,20 @@
|
|||||||
if (!iteratorName) {
|
if (!iteratorName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var snippet,
|
var funcNames = [],
|
||||||
funcNames = [],
|
objectSnippets = [];
|
||||||
objectSnippets = [],
|
|
||||||
token = '__isTypeToken__';
|
|
||||||
|
|
||||||
// build replacement code
|
// build replacement code
|
||||||
lodash.forOwn({
|
lodash.forOwn({
|
||||||
'Arguments': "'[object Arguments]'",
|
|
||||||
'Date': 'dateClass',
|
'Date': 'dateClass',
|
||||||
'Function': 'funcClass',
|
|
||||||
'Number': 'numberClass',
|
'Number': 'numberClass',
|
||||||
'RegExp': 'regexpClass',
|
'RegExp': 'regexpClass',
|
||||||
'String': 'stringClass'
|
'String': 'stringClass'
|
||||||
}, function(value, key) {
|
}, function(value, key) {
|
||||||
// skip `isArguments` if a legacy build
|
|
||||||
if (isLegacy && key == 'Arguments') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var funcName = 'is' + key,
|
var funcName = 'is' + key,
|
||||||
funcCode = matchFunction(source, funcName);
|
funcCode = matchFunction(source, funcName);
|
||||||
|
|
||||||
if (funcCode) {
|
if (funcCode) {
|
||||||
if (!snippet) {
|
|
||||||
// use snippet to mark the insert position
|
|
||||||
snippet = funcCode;
|
|
||||||
}
|
|
||||||
funcNames.push(funcName);
|
funcNames.push(funcName);
|
||||||
objectSnippets.push("'" + key + "': " + value);
|
objectSnippets.push("'" + key + "': " + value);
|
||||||
}
|
}
|
||||||
@@ -722,30 +885,22 @@
|
|||||||
if (funcNames.length < 2) {
|
if (funcNames.length < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// add a token to mark the position to insert new code
|
|
||||||
source = source.replace(snippet, '\n' + token + '\n' + snippet);
|
|
||||||
|
|
||||||
// remove existing isType functions
|
// remove existing isType functions
|
||||||
funcNames.forEach(function(funcName) {
|
funcNames.forEach(function(funcName) {
|
||||||
source = removeFunction(source, funcName);
|
source = removeFunction(source, funcName);
|
||||||
});
|
});
|
||||||
|
|
||||||
// replace token with new DRY code
|
// insert new DRY code after the method assignments
|
||||||
source = source.replace(token,
|
var snippet = getMethodAssignments(source);
|
||||||
|
source = source.replace(snippet, snippet + '\n' +
|
||||||
' // add `_.' + funcNames.join('`, `_.') + '`\n' +
|
' // add `_.' + funcNames.join('`, `_.') + '`\n' +
|
||||||
' ' + iteratorName + '({\n ' + objectSnippets.join(',\n ') + '\n }, function(className, key) {\n' +
|
' ' + iteratorName + '({\n ' + objectSnippets.join(',\n ') + '\n }, function(className, key) {\n' +
|
||||||
" lodash['is' + key] = function(value) {\n" +
|
" lodash['is' + key] = function(value) {\n" +
|
||||||
' return toString.call(value) == className;\n' +
|
' return toString.call(value) == className;\n' +
|
||||||
' };\n' +
|
' };\n' +
|
||||||
' });'
|
' });\n'
|
||||||
);
|
);
|
||||||
|
|
||||||
// tweak `isArguments` fallback
|
|
||||||
snippet = !isLegacy && getIsArgumentsFallback(source);
|
|
||||||
if (snippet) {
|
|
||||||
var modified = '\n' + snippet.replace(/isArguments/g, 'lodash.$&');
|
|
||||||
source = source.replace(snippet, modified);
|
|
||||||
}
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -760,11 +915,11 @@
|
|||||||
modified = snippet;
|
modified = snippet;
|
||||||
|
|
||||||
// remove native `Function#bind` branch in `_.bind`
|
// remove native `Function#bind` branch in `_.bind`
|
||||||
if (funcName == 'bind' ) {
|
if (funcName == 'bind') {
|
||||||
modified = modified.replace(/(?:\s*\/\/.*)*\s*else if *\(isBindFast[^}]+}/, '');
|
modified = modified.replace(/(?:\s*\/\/.*)*\s*else if *\(isBindFast[^}]+}/, '');
|
||||||
}
|
}
|
||||||
// remove native `Array.isArray` branch in `_.isArray`
|
// remove native `Array.isArray` branch in `_.isArray`
|
||||||
else if (funcName == 'isArray') {
|
else {
|
||||||
modified = modified.replace(/nativeIsArray * \|\|/, '');
|
modified = modified.replace(/nativeIsArray * \|\|/, '');
|
||||||
}
|
}
|
||||||
source = source.replace(snippet, modified);
|
source = source.replace(snippet, modified);
|
||||||
@@ -782,8 +937,8 @@
|
|||||||
// replace `_.isArguments` with fallback
|
// replace `_.isArguments` with fallback
|
||||||
if (!isRemoved(source, 'isArguments')) {
|
if (!isRemoved(source, 'isArguments')) {
|
||||||
source = source.replace(
|
source = source.replace(
|
||||||
matchFunction(source, 'isArguments').replace(/[\s\S]+?var isArguments *=/, ''),
|
matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''),
|
||||||
getIsArgumentsFallback(source).match(/isArguments *=([\s\S]+?) *};/)[1] + ' };\n'
|
getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n'
|
||||||
);
|
);
|
||||||
|
|
||||||
source = removeIsArgumentsFallback(source);
|
source = removeIsArgumentsFallback(source);
|
||||||
@@ -808,25 +963,37 @@
|
|||||||
source = source.replace(reFunc, '$1' + getFunctionSource(lodash[funcName]) + ';\n');
|
source = source.replace(reFunc, '$1' + getFunctionSource(lodash[funcName]) + ';\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// replace `callee` in `_.merge` with `merge`
|
||||||
|
source = source.replace(matchFunction(source, 'merge'), function(match) {
|
||||||
|
return match.replace(/\bcallee\b/g, 'merge');
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove `hasDontEnumBug`, `iteratesOwnLast`, `noArgsEnum` assignment
|
||||||
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b[\s\S]+?}\(1\)\);\n/, '');
|
||||||
|
|
||||||
|
// remove `iteratesOwnLast` from `isPlainObject`
|
||||||
|
source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(iteratesOwnLast[\s\S]+?\n\1}/, '');
|
||||||
|
|
||||||
// remove JScript [[DontEnum]] fix from `_.isEqual`
|
// remove JScript [[DontEnum]] fix from `_.isEqual`
|
||||||
source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(result *&& *hasDontEnumBug[\s\S]+?\n\1}/, '');
|
source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(hasDontEnumBug[\s\S]+?\n\1}/, '');
|
||||||
|
|
||||||
// remove IE `shift` and `splice` fix from mutator Array functions mixin
|
// remove IE `shift` and `splice` fix from mutator Array functions mixin
|
||||||
source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(value.length *=== *0[\s\S]+?\n\1}/, '');
|
source = source.replace(/(?:\s*\/\/.*)*\n( +)if *\(value.length *=== *0[\s\S]+?\n\1}/, '');
|
||||||
|
|
||||||
// remove `noCharByIndex` from `_.reduceRight`
|
|
||||||
source = source.replace(/noCharByIndex *&&[^:]+: *([^;]+)/g, '$1');
|
|
||||||
|
|
||||||
// remove `noArraySliceOnStrings` from `_.toArray`
|
// remove `noArraySliceOnStrings` from `_.toArray`
|
||||||
source = source.replace(/noArraySliceOnStrings *\?[^:]+: *([^)]+)/g, '$1');
|
source = source.replace(/noArraySliceOnStrings *\?[^:]+: *([^)]+)/g, '$1');
|
||||||
|
|
||||||
|
// remove `noCharByIndex` from `_.reduceRight`
|
||||||
|
source = source.replace(/noCharByIndex *&&[^:]+: *([^;]+)/g, '$1');
|
||||||
|
|
||||||
source = removeVar(source, 'extendIteratorOptions');
|
source = removeVar(source, 'extendIteratorOptions');
|
||||||
source = removeVar(source, 'hasDontEnumBug');
|
|
||||||
source = removeVar(source, 'iteratorTemplate');
|
source = removeVar(source, 'iteratorTemplate');
|
||||||
source = removeVar(source, 'noArraySliceOnStrings');
|
source = removeVar(source, 'noArraySliceOnStrings');
|
||||||
source = removeVar(source, 'noCharByIndex');
|
source = removeVar(source, 'noCharByIndex');
|
||||||
source = removeIsArgumentsFallback(source);
|
source = removeIsArgumentsFallback(source);
|
||||||
source = removeKeysOptimization(source);
|
source = removeKeysOptimization(source);
|
||||||
|
source = removeNoArgsClass(source);
|
||||||
|
source = removeNoNodeClass(source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// inline `iteratorTemplate` template
|
// inline `iteratorTemplate` template
|
||||||
@@ -836,23 +1003,18 @@
|
|||||||
// prepend data object references to property names to avoid having to
|
// prepend data object references to property names to avoid having to
|
||||||
// use a with-statement
|
// use a with-statement
|
||||||
iteratorOptions.forEach(function(property) {
|
iteratorOptions.forEach(function(property) {
|
||||||
if (property == 'iteratee') {
|
snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
|
||||||
// use a more fine-grained regexp for the `iteratee` property because
|
|
||||||
// it's a compiled variable as well as a data property
|
|
||||||
snippet = snippet.replace(/(__t *= *\( *)(iteratee)/, '$1obj.$2');
|
|
||||||
} else {
|
|
||||||
snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove unnecessary code
|
// remove unnecessary code
|
||||||
snippet = snippet
|
snippet = snippet
|
||||||
.replace(/, *__t,[^;]+|function print[^}]+}/g, '')
|
.replace(/var __t.+/, "var __p = '';")
|
||||||
|
.replace(/function print[^}]+}/, '')
|
||||||
.replace(/'(?:\\n|\s)+'/g, "''")
|
.replace(/'(?:\\n|\s)+'/g, "''")
|
||||||
.replace(/__p *\+= *' *';/g, '')
|
.replace(/__p *\+= *' *';/g, '')
|
||||||
.replace(/(__p *\+= *)' *' *\+/g, '$1')
|
.replace(/(__p *\+= *)' *' *\+/g, '$1')
|
||||||
.replace(/(\{) *;|; *(\})/g, '$1$2')
|
.replace(/(\{) *;|; *(\})/g, '$1$2')
|
||||||
.replace(/\(\(__w?t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__w?t\)/g, '$1');
|
.replace(/\(\(__t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__t\)/g, '$1');
|
||||||
|
|
||||||
// remove the with-statement
|
// remove the with-statement
|
||||||
snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1');
|
snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1');
|
||||||
@@ -860,7 +1022,7 @@
|
|||||||
// minor cleanup
|
// minor cleanup
|
||||||
snippet = snippet
|
snippet = snippet
|
||||||
.replace(/obj *\|\| *\(obj *= *\{}\);/, '')
|
.replace(/obj *\|\| *\(obj *= *\{}\);/, '')
|
||||||
.replace(/var __p;\s*__p/, 'var __p');
|
.replace(/var __p = '';\s*__p \+=/, 'var __p =');
|
||||||
|
|
||||||
// remove comments, including sourceURLs
|
// remove comments, including sourceURLs
|
||||||
snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, '');
|
snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, '');
|
||||||
@@ -871,22 +1033,87 @@
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// remove associated functions, variables, and code snippets that the minifier may miss
|
||||||
|
if (isRemoved(source, 'bind')) {
|
||||||
|
source = removeVar(source, 'nativeBind');
|
||||||
|
source = removeVar(source, 'isBindFast');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'isArray')) {
|
||||||
|
source = removeVar(source, 'nativeIsArray');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'isFunction')) {
|
||||||
|
source = removeIsFunctionFallback(source);
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'keys')) {
|
||||||
|
source = removeFunction(source, 'shimKeys');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'mixin')) {
|
||||||
|
// remove `LoDash` constructor
|
||||||
|
source = removeFunction(source, 'LoDash');
|
||||||
|
// remove `LoDash` calls
|
||||||
|
source = source.replace(/(?:new +LoDash(?!\()|(?:new +)?LoDash\([^)]*\));?/g, '');
|
||||||
|
// remove `LoDash.prototype` additions
|
||||||
|
source = source.replace(/(?:\s*\/\/.*)*\s*LoDash.prototype *=[\s\S]+?\/\*-+\*\//, '');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'template')) {
|
||||||
|
// remove `templateSettings` assignment
|
||||||
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, '');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'toArray')) {
|
||||||
|
source = removeVar(source, 'noArraySliceOnStrings');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'clone', 'merge')) {
|
||||||
|
source = removeFunction(source, 'isPlainObject');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'clone', 'isArguments', 'isEmpty', 'isEqual', 'size')) {
|
||||||
|
source = removeNoArgsClass(source);
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'isEqual', 'isPlainObject')) {
|
||||||
|
source = removeNoNodeClass(source);
|
||||||
|
}
|
||||||
|
if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
|
||||||
|
source = removeFunction(source, 'createIterator');
|
||||||
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var noArgsEnum;|.+?noArgsEnum *=.+/g, '');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'createIterator', 'bind', 'isArray', 'keys')) {
|
||||||
|
source = removeVar(source, 'reNative');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'createIterator', 'clone', 'merge')) {
|
||||||
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var iteratesOwnLast;|.+?iteratesOwnLast *=.+/g, '');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'createIterator', 'isEqual')) {
|
||||||
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug;|.+?hasDontEnumBug *=.+/g, '');
|
||||||
|
}
|
||||||
|
if (isRemoved(source, 'createIterator', 'keys')) {
|
||||||
|
source = removeVar(source, 'nativeKeys');
|
||||||
|
}
|
||||||
|
if (!source.match(/var (?:hasDontEnumBug|iteratesOwnLast|noArgsEnum)\b/g)) {
|
||||||
|
// remove `hasDontEnumBug`, `iteratesOwnLast`, `noArgsEnum` assignment
|
||||||
|
source = source.replace(/ *\(function\(\) *{\s*var props\b[\s\S]+?}\(1\)\);/, '');
|
||||||
|
}
|
||||||
|
|
||||||
// remove pseudo private properties
|
// remove pseudo private properties
|
||||||
source = source.replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n');
|
source = source.replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n');
|
||||||
|
|
||||||
|
// consolidate consecutive horizontal rule comment separators
|
||||||
|
source = source.replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) {
|
||||||
|
return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*'));
|
||||||
|
});
|
||||||
|
|
||||||
// cleanup code
|
// cleanup code
|
||||||
source = source.replace(/^ *;\n/gm, '');
|
source = source.replace(/^ *;\n/gm, '');
|
||||||
|
|
||||||
// begin the minification process
|
// begin the minification process
|
||||||
if (filterType || isBackbone || isLegacy || isMobile) {
|
if (filterType || isBackbone || isLegacy || isMobile || isStrict || isUnderscore) {
|
||||||
fs.writeFileSync(path.join(cwd, 'lodash.custom.js'), source);
|
writeFile(source, 'lodash.custom.js');
|
||||||
|
|
||||||
minify(source, 'lodash.custom.min', function(result) {
|
minify(source, 'lodash.custom.min', function(result) {
|
||||||
fs.writeFileSync(path.join(cwd, 'lodash.custom.min.js'), result);
|
writeFile(result, 'lodash.custom.min.js');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
minify(source, 'lodash.min', function(result) {
|
minify(source, 'lodash.min', function(result) {
|
||||||
fs.writeFileSync(path.join(cwd, 'lodash.min.js'), result);
|
writeFile(result, 'lodash.min.js');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -34,14 +34,11 @@
|
|||||||
// move vars exposed by Closure Compiler into the IIFE
|
// move vars exposed by Closure Compiler into the IIFE
|
||||||
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
|
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
|
||||||
|
|
||||||
// use double quotes consistently
|
|
||||||
source = source.replace(/'use strict'/, '"use strict"');
|
|
||||||
|
|
||||||
// unescape properties (i.e. foo["bar"] => foo.bar)
|
// unescape properties (i.e. foo["bar"] => foo.bar)
|
||||||
source = source.replace(/(\w)\["([^."]+)"\]/g, '$1.$2');
|
source = source.replace(/(\w)\["([^."]+)"\]/g, '$1.$2');
|
||||||
|
|
||||||
// correct AMD module definition for AMD build optimizers
|
// correct AMD module definition for AMD build optimizers
|
||||||
source = source.replace(/("function")==(typeof define)&&\(?("object")==(typeof define\.amd)(&&define\.amd)\)?/, '$2==$1&&$4==$3$5');
|
source = source.replace(/("function")\s*==\s*(typeof define)\s*&&\s*\(?\s*("object")\s*==\s*(typeof define\.amd)\s*&&\s*(define\.amd)\s*\)?/, '$2==$1&&$4==$3&&$5');
|
||||||
|
|
||||||
// add license
|
// add license
|
||||||
source = license + '\n;' + source;
|
source = license + '\n;' + source;
|
||||||
|
|||||||
@@ -7,42 +7,69 @@
|
|||||||
|
|
||||||
/** Used to minify variables embedded in compiled strings */
|
/** Used to minify variables embedded in compiled strings */
|
||||||
var compiledVars = [
|
var compiledVars = [
|
||||||
'accumulator',
|
|
||||||
'args',
|
|
||||||
'arrayClass',
|
|
||||||
'callback',
|
'callback',
|
||||||
'className',
|
|
||||||
'collection',
|
'collection',
|
||||||
'compareAscending',
|
'concat',
|
||||||
'ctor',
|
'ctor',
|
||||||
'funcClass',
|
|
||||||
'hasOwnProperty',
|
'hasOwnProperty',
|
||||||
'identity',
|
'identity',
|
||||||
'index',
|
'index',
|
||||||
'isFunc',
|
|
||||||
'iteratee',
|
'iteratee',
|
||||||
'iteratorBind',
|
'iteratorBind',
|
||||||
'length',
|
'length',
|
||||||
'methodName',
|
|
||||||
'nativeKeys',
|
'nativeKeys',
|
||||||
'noaccum',
|
|
||||||
'object',
|
'object',
|
||||||
'objectTypes',
|
'ownIndex',
|
||||||
|
'ownProps',
|
||||||
'prop',
|
'prop',
|
||||||
|
'propertyIsEnumerable',
|
||||||
'propIndex',
|
'propIndex',
|
||||||
'props',
|
'props',
|
||||||
'property',
|
|
||||||
'propertyIsEnumerable',
|
|
||||||
'result',
|
'result',
|
||||||
'skipProto',
|
'skipProto',
|
||||||
'slice',
|
'slice',
|
||||||
'source',
|
|
||||||
'sourceIndex',
|
|
||||||
'stringClass',
|
'stringClass',
|
||||||
'target',
|
|
||||||
'thisArg',
|
'thisArg',
|
||||||
'toString',
|
'toString',
|
||||||
'value'
|
'value',
|
||||||
|
|
||||||
|
// lesser used variables
|
||||||
|
'accumulator',
|
||||||
|
'args',
|
||||||
|
'argsIndex',
|
||||||
|
'argsLength',
|
||||||
|
'arrayLikeClasses',
|
||||||
|
'ArrayProto',
|
||||||
|
'bind',
|
||||||
|
'callee',
|
||||||
|
'className',
|
||||||
|
'compareAscending',
|
||||||
|
'destValue',
|
||||||
|
'forIn',
|
||||||
|
'found',
|
||||||
|
'funcs',
|
||||||
|
'indexOf',
|
||||||
|
'indicator',
|
||||||
|
'isArguments',
|
||||||
|
'isArr',
|
||||||
|
'isArray',
|
||||||
|
'isFunc',
|
||||||
|
'isFunction',
|
||||||
|
'isPlainObject',
|
||||||
|
'methodName',
|
||||||
|
'noaccum',
|
||||||
|
'objectClass',
|
||||||
|
'objectTypes',
|
||||||
|
'pass',
|
||||||
|
'properties',
|
||||||
|
'property',
|
||||||
|
'propsLength',
|
||||||
|
'recursive',
|
||||||
|
'source',
|
||||||
|
'stack',
|
||||||
|
'stackLength',
|
||||||
|
'target',
|
||||||
|
'valueProp'
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to minify `compileIterator` option properties */
|
/** Used to minify `compileIterator` option properties */
|
||||||
@@ -58,17 +85,21 @@
|
|||||||
'inLoop',
|
'inLoop',
|
||||||
'init',
|
'init',
|
||||||
'isKeysFast',
|
'isKeysFast',
|
||||||
'iteratee',
|
|
||||||
'object',
|
'object',
|
||||||
'objectBranch',
|
'objectBranch',
|
||||||
|
'noArgsEnum',
|
||||||
'noCharByIndex',
|
'noCharByIndex',
|
||||||
'shadowed',
|
'shadowed',
|
||||||
'top',
|
'top',
|
||||||
'useHas'
|
'useHas',
|
||||||
|
'useStrict'
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to minify variables and string values to a single character */
|
/** Used to minify variables and string values to a single character */
|
||||||
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||||
|
minNames.push.apply(minNames, minNames.map(function(value) {
|
||||||
|
return value + value;
|
||||||
|
}));
|
||||||
|
|
||||||
/** Used to protect the specified properties from getting minified */
|
/** Used to protect the specified properties from getting minified */
|
||||||
var propWhitelist = [
|
var propWhitelist = [
|
||||||
@@ -89,6 +120,7 @@
|
|||||||
'compact',
|
'compact',
|
||||||
'compose',
|
'compose',
|
||||||
'contains',
|
'contains',
|
||||||
|
'countBy',
|
||||||
'criteria',
|
'criteria',
|
||||||
'debounce',
|
'debounce',
|
||||||
'defaults',
|
'defaults',
|
||||||
@@ -96,6 +128,7 @@
|
|||||||
'delay',
|
'delay',
|
||||||
'detect',
|
'detect',
|
||||||
'difference',
|
'difference',
|
||||||
|
'drop',
|
||||||
'each',
|
'each',
|
||||||
'environment',
|
'environment',
|
||||||
'escape',
|
'escape',
|
||||||
@@ -118,6 +151,7 @@
|
|||||||
'head',
|
'head',
|
||||||
'identity',
|
'identity',
|
||||||
'include',
|
'include',
|
||||||
|
'index',
|
||||||
'indexOf',
|
'indexOf',
|
||||||
'initial',
|
'initial',
|
||||||
'inject',
|
'inject',
|
||||||
@@ -148,6 +182,7 @@
|
|||||||
'map',
|
'map',
|
||||||
'max',
|
'max',
|
||||||
'memoize',
|
'memoize',
|
||||||
|
'merge',
|
||||||
'methods',
|
'methods',
|
||||||
'min',
|
'min',
|
||||||
'mixin',
|
'mixin',
|
||||||
@@ -187,6 +222,7 @@
|
|||||||
'values',
|
'values',
|
||||||
'variable',
|
'variable',
|
||||||
'VERSION',
|
'VERSION',
|
||||||
|
'where',
|
||||||
'without',
|
'without',
|
||||||
'wrap',
|
'wrap',
|
||||||
'zip',
|
'zip',
|
||||||
@@ -208,15 +244,28 @@
|
|||||||
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
||||||
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
||||||
|
|
||||||
|
// manually convert `arrayLikeClasses` property assignments because
|
||||||
|
// Closure Compiler errors trying to minify them
|
||||||
|
source = source.replace(/(arrayLikeClasses =)[\s\S]+?= *true/,
|
||||||
|
"$1{'[object Arguments]': true, '[object Array]': true, '[object Boolean]': false, " +
|
||||||
|
"'[object Date]': false, '[object Function]': false, '[object Number]': false, " +
|
||||||
|
"'[object Object]': false, '[object RegExp]': false, '[object String]': true }"
|
||||||
|
);
|
||||||
|
|
||||||
|
// manually convert `cloneableClasses` property assignments because
|
||||||
|
// Closure Compiler errors trying to minify them
|
||||||
|
source = source.replace(/(cloneableClasses =)[\s\S]+?= *true/,
|
||||||
|
"$1{'[object Arguments]': false, '[object Array]': true, '[object Boolean]': true, " +
|
||||||
|
"'[object Date]': true, '[object Function]': false, '[object Number]': true, " +
|
||||||
|
"'[object Object]': true, '[object RegExp]': true, '[object String]': true }"
|
||||||
|
);
|
||||||
|
|
||||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
||||||
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||||
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
||||||
|
|
||||||
// remove brackets from `_.escape()` in `tokenizeEscape`
|
|
||||||
source = source.replace(/_\['escape']\("/, '_.escape("');
|
|
||||||
|
|
||||||
// remove brackets from `_.escape()` in `_.template`
|
// remove brackets from `_.escape()` in `_.template`
|
||||||
source = source.replace(/__e *= *_\['escape']/, '__e=_.escape');
|
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
|
||||||
|
|
||||||
// remove brackets from `collection.indexOf` in `_.contains`
|
// remove brackets from `collection.indexOf` in `_.contains`
|
||||||
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
|
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
|
||||||
@@ -232,7 +281,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove whitespace from `_.template` related regexpes
|
// remove whitespace from `_.template` related regexes
|
||||||
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
||||||
return match.replace(/ |\\n/g, '');
|
return match.replace(/ |\\n/g, '');
|
||||||
});
|
});
|
||||||
@@ -246,35 +295,59 @@
|
|||||||
.replace("') {\\n'", "'){'")
|
.replace("') {\\n'", "'){'")
|
||||||
|
|
||||||
// remove `useSourceURL` variable
|
// remove `useSourceURL` variable
|
||||||
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*\n)* *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');
|
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');
|
||||||
|
|
||||||
// remove debug sourceURL use in `_.template`
|
// remove debug sourceURL use in `_.template`
|
||||||
source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');
|
source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');
|
||||||
|
|
||||||
// minify internal properties used by `_.sortBy`
|
// minify internal properties used by 'compareAscending', `_.clone`, `_.merge`, and `_.sortBy`
|
||||||
(function() {
|
(function() {
|
||||||
var properties = ['criteria', 'value'],
|
var properties = ['criteria', 'index', 'source', 'value'],
|
||||||
snippets = source.match(/( +)(?:function compareAscending|var sortBy)\b[\s\S]+?\n\1}/g);
|
snippets = source.match(/( +)(?:function clone|function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
|
||||||
|
|
||||||
if (!snippets) {
|
if (!snippets) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
snippets.forEach(function(snippet) {
|
snippets.forEach(function(snippet) {
|
||||||
var modified = snippet,
|
var modified = snippet,
|
||||||
isSortBy = /var sortBy\b/.test(modified),
|
isCompilable = /(?:var merge|var sortBy)\b/.test(modified),
|
||||||
isInlined = !/\bcreateIterator\b/.test(modified);
|
isInlined = !/\bcreateIterator\b/.test(modified);
|
||||||
|
|
||||||
// minify properties
|
// minify properties
|
||||||
properties.forEach(function(property, index) {
|
properties.forEach(function(property, index) {
|
||||||
// add quotes around properties in the inlined `_.sortBy` of the mobile
|
var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
|
||||||
// build so Closure Compiler won't mung them
|
reDotProp = RegExp('\\.' + property + '\\b', 'g'),
|
||||||
if (isSortBy && isInlined) {
|
rePropColon = RegExp("(')?\\b" + property + "\\1 *:", 'g');
|
||||||
modified = modified
|
|
||||||
.replace(RegExp('\\.' + property + '\\b', 'g'), "['" + minNames[index] + "']")
|
if (isCompilable) {
|
||||||
.replace(RegExp('\\b' + property + ' *:', 'g'), "'" + minNames[index] + "':");
|
// add quotes around properties in the inlined `_.merge` and `_.sortBy`
|
||||||
|
// of the mobile build so Closure Compiler won't mung them
|
||||||
|
if (isInlined) {
|
||||||
|
modified = modified
|
||||||
|
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||||
|
.replace(reDotProp, "['" + minNames[index] + "']")
|
||||||
|
.replace(rePropColon, "'" + minNames[index] + "':");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modified = modified
|
||||||
|
.replace(reBracketProp, '.' + minNames[index])
|
||||||
|
.replace(reDotProp, '.' + minNames[index])
|
||||||
|
.replace(rePropColon, minNames[index] + ':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modified = modified
|
||||||
|
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||||
|
.replace(reDotProp, '.' + minNames[index])
|
||||||
|
.replace(rePropColon, "'" + minNames[index] + "':")
|
||||||
|
|
||||||
|
// correct `value.source` in regexp branch of `_.clone`
|
||||||
|
if (property == 'source') {
|
||||||
|
modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// replace with modified snippet
|
// replace with modified snippet
|
||||||
source = source.replace(snippet, modified);
|
source = source.replace(snippet, modified);
|
||||||
});
|
});
|
||||||
@@ -308,8 +381,8 @@
|
|||||||
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");
|
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");
|
||||||
|
|
||||||
if (isCreateIterator) {
|
if (isCreateIterator) {
|
||||||
// replace with modified snippet early and clip snippet so other arguments
|
// replace with modified snippet early and clip snippet to the `factory`
|
||||||
// aren't minified
|
// call so other arguments aren't minified
|
||||||
source = source.replace(snippet, modified);
|
source = source.replace(snippet, modified);
|
||||||
snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
|
snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
|
||||||
}
|
}
|
||||||
@@ -339,7 +412,7 @@
|
|||||||
else {
|
else {
|
||||||
// minify property name strings
|
// minify property name strings
|
||||||
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
||||||
// minify property names in regexps and accessors
|
// minify property names in regexes and accessors
|
||||||
if (isCreateIterator) {
|
if (isCreateIterator) {
|
||||||
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
||||||
}
|
}
|
||||||
|
|||||||
914
doc/README.md
914
doc/README.md
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
|||||||
// generate Markdown
|
// generate Markdown
|
||||||
$markdown = docdown(array(
|
$markdown = docdown(array(
|
||||||
'path' => '../' . $file,
|
'path' => '../' . $file,
|
||||||
'title' => 'Lo-Dash <sup>v0.4.0</sup>',
|
'title' => 'Lo-Dash <sup>v0.5.2</sup>',
|
||||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
70
lodash.min.js
vendored
70
lodash.min.js
vendored
@@ -1,35 +1,41 @@
|
|||||||
/*!
|
/*!
|
||||||
Lo-Dash 0.4.0 lodash.com/license
|
Lo-Dash 0.5.2 lodash.com/license
|
||||||
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
|
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
;(function(e,t){"use strict";function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",q:"",c:{d:""},n:{d:""}};++s<o;)for(t in e=arguments[s],e)n=(n=e[t])==r?"":n,/d|i/.test(t)?("string"==typeof n&&(n={b:n,m:n}),u.c[t]=n.b,u.n[t]=n.m):u[t]=n;e=u.a,t=/^[^,]+/.exec(e)[0],u.l=u.l||t,u.g=t,u.h=yt,u.k=St,u.p=Q,u.r=u.r!==i,"o"in u||(u.o=wt),u.f||(u.f="if(!"+t+")return A");if("f"!=t||!u.c.i)u.c=r;t="var A",u.
|
;(function(e,t){"use strict";function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||30),s=i?{}:e;if(i)for(var o=t-1;++o<r;)n=e[o]+"",(ot.call(s,n)?s[n]:s[n]=[]).push(e[o]);return function(e){if(i){var n=e+"";return ot.call(s,n)&&-1<C(s[n],e)}return-1<C(s,e,t)}}function a(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",q:"",c:{d:""},m:{d:""}};++s<o;)for(t in e=arguments[s],e)n=(n=e[t])==r?"":n,/d|i/.test(t
|
||||||
j&&(t+="="+u.j),t+=";"+u.f+";"+u.q+";var l,n="+u.l+";",u.c&&(t+="var p=n.length;l=-1;",u.n&&(t+="if(p===p>>>0){"),u.o&&(t+="if(I.call(n)==F){n=n.split('')}"),t+=u.c.d+";while(++l<p){"+u.c.i+"}",u.n&&(t+="}"));if(u.n){u.c&&(t+="else{"),u.h||(t+="var B=typeof n=='function'&&z.call(n,'prototype');"),u.k&&u.r?t+="var x=r(n),w=-1,p=x.length;"+u.n.d+";while(++w<p){l=x[w];if(!(B&&l=='prototype')){"+u.n.i+"}}":(t+=u.n.d+";for(l in n){",u.h?(u.r&&(t+="if(j.call(n,l)){"),t+=u.n.i+";",u.r&&(t+="}")):(t+="if(!(B&&l=='prototype')"
|
)?("string"==typeof n&&(n={b:n,l:n}),u.c[t]=n.b,u.m[t]=n.l):u[t]=n;e=u.a,t=/^[^,]+/.exec(e)[0],u.g=t,u.h=Nt,u.k=Pt,u.n=kt,u.p=nt,u.r=u.r!==i,u.s=u.s!==i,"o"in u||(u.o=Ot),u.f||(u.f="if(!"+t+")return s");if("b"!=t||!u.c.i)u.c=r;t="",u.s&&(t+="'use strict';"),t+="var g,y,h="+u.g+",s",u.j&&(t+="="+u.j),t+=";"+u.f+";"+u.q+";",u.c&&(t+="var j=h.length;g=-1;",u.m&&(t+="if(j>-1&&j===j>>>0){"),u.o&&(t+="if(x.call(h)==v){h=h.split('')}"),t+=u.c.d+";while(++g<j){y=h[g];"+u.c.i+"}",u.m&&(t+="}"));if(u.m){u.
|
||||||
,u.r&&(t+="&&j.call(n,l)"),t+="){"+u.n.i+"}"),t+="}");if(u.h){t+="var h=n.constructor;";for(n=0;7>n;n++)t+="l='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(h&&h.prototype===n)&&"),t+="j.call(n,l)){"+u.n.i+"}"}u.c&&(t+="}")}return t+=u.e+";return A",Function("c,g,i,j,k,o,u,r,z,C,F,I",'"use strict";return function('+e+"){"+t+"}")(ft,a,ht,et,k,h,Tt,at,nt,rt,vt,it)}function a(e,n){return e=e.a,n=n.a,e===t?1:n===t?-1:e<n?-1:e>n?1:0}function f(e,t){return Y[t]}function l(e){return"\\"+Nt[e]}function c
|
c?t+="else{":u.n&&(t+="var j=h.length;g=-1;if(j&&P(h)){while(++g<j){y=h[g+=''];"+u.m.i+"}}else{"),u.h||(t+="var t=typeof h=='function'&&p.call(h,'prototype');"),u.k&&u.r?(t+="var m=-1,n=Y[typeof h]?k(h):[],j=n.length;"+u.m.d+";while(++m<j){g=n[m];",u.h||(t+="if(!(t&&g=='prototype')){"),t+="y=h[g];"+u.m.i+"",u.h||(t+="}")):(t+=u.m.d+";for(g in h){",u.h?(u.r&&(t+="if(e.call(h,g)){"),t+="y=h[g];"+u.m.i+";",u.r&&(t+="}")):(t+="if(!(t&&g=='prototype')",u.r&&(t+="&&e.call(h,g)"),t+="){y=h[g];"+u.m.i+"}"
|
||||||
(e){return xt[e]}function h(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function p(){}function d(e,t){if(F.test(t))return"<e%-"+t+"%>";var n=Y.length;return Y[n]="'+__e("+t+")+'",G+n}function v(e,t,n,r){return e=Y.length,t?Y[e]="';"+t+";__p+='":n?Y[e]="'+__we("+n+")+'":r&&(Y[e]="'+((__wt=("+r+"))==null?'':__wt)+'"),G+e}function m(e,t){if(F.test(t))return"<e%="+t+"%>";var n=Y.length;return Y[n]="'+((__t=("+t+"))==null?'':__t)+'",G+n}function g(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments
|
)),t+="}";if(u.h){t+="var d=h.constructor;";for(n=0;7>n;n++)t+="g='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(d&&d.prototype===h)&&"),t+="e.call(h,g)){y=h[g];"+u.m.i+"}"}if(u.c||u.n)t+="}"}return t+=u.e+";return s",Function("D,E,F,I,c,K,e,f,N,P,R,T,U,i,X,Y,k,p,u,v,x","var G=function("+e+"){"+t+"};return G")(Ht,I,M,f,st,Zt,ot,_,C,b,Jt,w,p,d,wt,Ft,dt,at,ft,St,lt)}function f(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;return e===t?1:n===t?-1:e<n?-1:e>n?1:r<i?-1:1}function l(e,t){return it[t]}function c(e){
|
||||||
.length;r&&(t=h(t,r));if(i===i>>>0){var o=wt&&it.call(e)==vt?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=en(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function y(e,t,n){if(e)return t==r||n?e[0]:rt.call(e,0,t)}function b(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length;++i<s;)r=e[i],Yt(r)?tt.apply(n,t?r:b(r)):n.push(r);return n}function w(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=x(e,t),e[r]===t?r:-1;
|
return"\\"+It[e]}function h(e){return jt[e]}function p(e,t){var n=i;if(!e||"object"!=typeof e||!t&&b(e))return n;var r=e.constructor;return(!Mt||"function"==typeof e.toString||"string"!=typeof (e+""))&&(!w(r)||r instanceof r)?Ct?(Zt(e,function(t,r){return n=!ot.call(e,r),i}),n===i):(Zt(e,function(e,t){n=t}),n===i||ot.call(e,n)):n}function d(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function v(){}function m(e,t){if(e&&V.test(t))return"<e%-"+t+"%>";var n=it.length;return it[n]="'+__e("+t+")+'"
|
||||||
r=(0>n?Math.max(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function E(e,t,n){var r=-Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]>i&&(i=e[s]);return i}for(n&&(t=h(t,n));++s<o;)n=t(e[s],s,e),n>r&&(r=n,i=e[s]);return i}function S(e,t,n){return e?rt.call(e,t==r||n?1:t):[]}function x(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=N(n,r));for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+s>>>1,e[r]<t?i=r+1:s=r;return i}function T(e,t,n,r){var s=
|
,rt+n}function g(e,t,n,i){return i?(e=it.length,it[e]="';"+i+";__p+='",rt+e):t?m(r,t):y(r,n)}function y(e,t){if(e&&V.test(t))return"<e%="+t+"%>";var n=it.length;return it[n]="'+((__t=("+t+"))==null?'':__t)+'",rt+n}function b(e){return lt.call(e)==vt}function w(e){return"function"==typeof e}function E(e,t,s,o,u){if(e==r)return e;s&&(t=i),u||(u={d:r}),u.d==r&&(u.d=!(!q.clone&&!U.clone&&!z.clone));if(((s=Ft[typeof e])||u.d)&&e.clone&&w(e.clone))return u.d=r,e.clone(t);if(s){var a=lt.call(e);if(!Bt[a
|
||||||
[];if(!e)return s;var o=-1,u=e.length,a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n?r&&(n=h(n,r)):n=k;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>w(a,r))a.push(r),s.push(e[o]);return s}function N(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?Z.apply(s,o):s),this instanceof n?(p.prototype=e.prototype,u=new p,(o=e.apply(u,o))&&Tt[typeof o]?o:u):e.apply(u,o)}var r,i=it.call(e)==ht;if(i){if(Et||st&&2<arguments.length)return st.call.apply(st,arguments)}else r=t,
|
]||Lt&&b(e))return e;var f=a==mt,s=f||(a==wt?p(e,n):s)}if(!s||!t)return s?f?ft.call(e):Yt({},e):e;s=e.constructor;switch(a){case gt:return new s(e==n);case yt:return new s(+e);case bt:case St:return new s(e);case Et:return s(e.source,Q.exec(e))}o||(o=[]);for(a=o.length;a--;)if(o[a].c==e)return o[a].d;var a=e.length,l=f?s(a):{};o.push({d:l,c:e});if(f)for(f=-1;++f<a;)l[f]=E(e[f],t,r,o,u);else en(e,function(e,n){l[n]=E(e,t,r,o,u)});return l}function S(e,t,s,o){if(e==r||t==r)return e===t;o||(o={value
|
||||||
t=e;var s=rt.call(arguments,2);return n}function C(e,t,s){s||(s=[]);if(e===t)return 0!==e||1/e==1/t;if(e==r||t==r)return e===t;e._chain&&(e=e._wrapped),t._chain&&(t=t._wrapped);if(e.isEqual&&it.call(e.isEqual)==ht)return e.isEqual(t);if(t.isEqual&&it.call(t.isEqual)==ht)return t.isEqual(e);var o=it.call(e);if(o!=it.call(t))return i;switch(o){case vt:return e==""+t;case pt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case lt:case ct:return+e==+t;case dt:return e.source==t.source&&e.global==t.global&&e.multiline==
|
:r}),o.value==r&&(o.value=!(!q.isEqual&&!U.isEqual&&!z.isEqual));if(Ft[typeof e]||Ft[typeof t]||o.value){e._chain&&(e=e._wrapped),t._chain&&(t=t._wrapped);if(e.isEqual&&w(e.isEqual))return o.value=r,e.isEqual(t);if(t.isEqual&&w(t.isEqual))return o.value=r,t.isEqual(e)}if(e===t)return 0!==e||1/e==1/t;var u=lt.call(e);if(u!=lt.call(t))return i;switch(u){case gt:case yt:return+e==+t;case bt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case Et:case St:return e==t+""}var a=Ht[u];if(Lt&&!a&&(a=b(e))&&!b(t)||!
|
||||||
t.multiline&&e.ignoreCase==t.ignoreCase}if("object"!=typeof e||"object"!=typeof t)return i;for(var u=s.length;u--;)if(s[u]==e)return n;var u=-1,a=n,f=0;s.push(e);if(o==ft){if(f=e.length,a=f==t.length)for(;f--&&(a=C(e[f],t[f],s)););}else{if("constructor"in e!="constructor"in t||e.constructor!=t.constructor)return i;for(var l in e)if(et.call(e,l)&&(f++,!(a=et.call(t,l)&&C(e[l],t[l],s))))break;if(a){for(l in t)if(et.call(t,l)&&!(f--))break;a=!f}if(a&&yt)for(;7>++u&&(l=Q[u],!et.call(e,l)||!!(a=et.call
|
a&&(u!=wt||Mt&&("function"!=typeof e.toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;s||(s=[]);for(u=s.length;u--;)if(s[u]==e)return n;var u=-1,f=n,l=0;s.push(e);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=S(e[l],t[l],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!w(a)||!(a instanceof a&&w(f)&&f instanceof f)))return i;for(var c in e)if(ot.call(e,c)&&(l++,!ot.call(t,c)||!S(e[c],t[c],s,o)))return i;for(c in t)if(ot.call(t,c)&&!(l--
|
||||||
(t,l)&&C(e[l],t[l],s))););}return s.pop(),a}function k(e){return e}function L(e){Ft(Gt(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this._wrapped];return arguments.length&&tt.apply(e,arguments),e=r.apply(s,e),this._chain&&(e=new o(e),e._chain=n),e}})}var n=!0,r=null,i=!1,A,O,M,_,D="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),P=Array.prototype,H=Object.prototype,B=0,j=e._,F=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/
|
))return i;if(Nt)for(;7>++u;)if(c=nt[u],ot.call(e,c)&&(!ot.call(t,c)||!S(e[c],t[c],s,o)))return i;return n}function x(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=d(t,r));if(-1<i&&i===i>>>0){var o=Ot&<.call(e)==St?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=rn(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function T(e,t,n){if(e)return t==r||n?e[0]:ft.call(e,0,t)}function N(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length
|
||||||
,I=/^';/,q=/^'\+/,R=/(?:__p\+='|\+')$/,U=/\b__p\+='';/g,z=/\b(__p\+?=)''\+/g,W=/(__w?e\(.*?\)|\b__w?t\))\+'';/g,X=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,V=RegExp("^"+(H.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),$=/__token__(\d+)/g,J=/[&<"']/g,K=/['\n\r\t\u2028\u2029\\]/g,Q="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),G="__token__",Y=[],Z=P.concat,et=H.hasOwnProperty,tt=P.push,nt=H
|
;++i<s;)r=e[i],Jt(r)?ut.apply(n,t?r:N(r)):n.push(r);return n}function C(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=A(e,t),e[r]===t?r:-1;r=(0>n?Math.max(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function k(e,t,n){var r=-Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]>i&&(i=e[s]);return i}for(n&&(t=d(t,n));++s<o;)n=t(e[s],s,e),n>r&&(r=n,i=e[s]);return i}function L(e,t,n){return e?ft.call(e,t==r||n?1:t):[]}function A(e,t,n,r){if(!
|
||||||
.propertyIsEnumerable,rt=P.slice,it=H.toString,st=V.test(st=rt.bind)&&st,ot=V.test(ot=Array.isArray)&&ot,ut=e.isFinite,at=V.test(at=Object.keys)&&at,ft="[object Array]",lt="[object Boolean]",ct="[object Date]",ht="[object Function]",pt="[object Number]",dt="[object RegExp]",vt="[object String]",mt=e.clearTimeout,gt=e.setTimeout,yt=!nt.call({valueOf:0},"valueOf"),bt="x"!=rt.call("x")[0],wt="xx"!="x"[0]+Object("x")[0],Et=st&&/\n|Opera/.test(st+it.call(e.opera)),St=at&&/^.+$|true/.test(at+!!e.attachEvent
|
e)return 0;var i=0,s=e.length;if(n){r&&(n=M(n,r));for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+s>>>1,e[r]<t?i=r+1:s=r;return i}function O(e,t,n,r){var s=[];if(!e)return s;var o=-1,u=e.length,a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n?r&&(n=d(n,r)):n=_;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>C(a,r))a.push(r),s.push(e[o]);return s}function M(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?s.concat(ft.call(o)):s),this instanceof n?(v.prototype=
|
||||||
),xt={"&":"&","<":"<",'"':""","'":"'"},Tt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i},Nt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"};var Ct={a:"f,d,H",j:"f",q:"if(!d){d=k}else if(H)d=o(d,H)",i:"d(n[l],l,f)"},kt={j:"true",i:"if(!d(n[l],l,f))return!A"},Lt={a:"t",j:"t",q:"for(var D,E=1,p=arguments.length;E<p;E++){D=arguments[E];"+
|
e.prototype,u=new v,(o=e.apply(u,o))&&Ft[typeof o]?o:u):e.apply(u,o)}var r,i=w(e);if(i){if(Dt||ct&&2<arguments.length)return ct.call.apply(ct,arguments)}else r=t,t=e;var s=ft.call(arguments,2);return n}function _(e){return e}function D(e){hn(tn(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this._wrapped];return arguments.length&&ut.apply(e,arguments),e=r.apply(s,e),this._chain&&(e=new o(e),e._chain=n),e}})}var n=!0,r=null,i=!1,P,H,B,j,F="object"==typeof exports&&exports&&("object"==typeof
|
||||||
(yt?"if(D){":""),l:"D",r:i,i:"A[l]=n[l]",e:(yt?"}":"")+"}"},At={j:"[]",i:"d(n[l],l,f)&&A.push(n[l])"},Ot={q:"if(H)d=o(d,H)"},Mt={i:{m:Ct.i}},_t={j:"",f:"if(!f)return[]",d:{b:"A=Array(p)",m:"A="+(St?"Array(p)":"[]")},i:{b:"A[l]=d(n[l],l,f)",m:"A"+(St?"[w]=":".push")+"(d(n[l],l,f))"}},Dt=u({a:"t",f:"if(!(t&&u[typeof t]))throw TypeError()",j:"[]",i:"A.push(l)"}),Pt=u({a:"f,G",j:"false",o:i,d:{b:"if(I.call(n)==F)return f.indexOf(G)>-1"},i:"if(n[l]===G)return true"}),Ht=u(Ct,kt),Bt=u(Ct,At),jt=u(Ct,Ot
|
global&&global&&global==global.global&&(e=global),exports),I=Array.prototype,q=Boolean.prototype,R=Object.prototype,U=Number.prototype,z=String.prototype,W=0,X=e._,V=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,$=/\b__p\+='';/g,J=/\b(__p\+=)''\+/g,K=/(__e\(.*?\)|\b__t\))\+'';/g,Q=/\w*$/,G=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,Y=RegExp("^"+(R.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),Z=/__token__(\d+)/g,et=/[&<"']/g
|
||||||
,{j:"",i:"if(d(n[l],l,f))return n[l]"}),Ft=u(Ct,Ot),It=u(Ct,{j:"{}",q:"var v,m=typeof d=='function';if(m&&H)d=o(d,H)",i:"v=m?d(n[l],l,f):n[l][d];(j.call(A,v)?A[v]:A[v]=[]).push(n[l])"}),qt=u(_t,{a:"f,q",q:"var b=C.call(arguments,2),m=typeof q=='function'",i:{b:"A[l]=(m?q:n[l][q]).apply(n[l],b)",m:"A"+(St?"[w]=":".push")+"((m?q:n[l][q]).apply(n[l],b))"}}),Rt=u(Ct,_t),Ut=u(_t,{a:"f,y",i:{b:"A[l]=n[l][y]",m:"A"+(St?"[w]=":".push")+"(n[l][y])"}}),zt=u({a:"f,d,a,H",j:"a",q:"var s=arguments.length<3;if(H)d=o(d,H)"
|
,tt=/['\n\r\t\u2028\u2029\\]/g,nt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),rt="__token__",it=[],st=I.concat,ot=R.hasOwnProperty,ut=I.push,at=R.propertyIsEnumerable,ft=I.slice,lt=R.toString,ct=Y.test(ct=ft.bind)&&ct,ht=Y.test(ht=Array.isArray)&&ht,pt=e.isFinite,dt=Y.test(dt=Object.keys)&&dt,vt="[object Arguments]",mt="[object Array]",gt="[object Boolean]",yt="[object Date]",bt="[object Number]",wt="[object Object]",Et="[object RegExp]"
|
||||||
,d:{b:"if(s)A=f[++l]"},i:{b:"A=d(A,n[l],l,f)",m:"A=s?(s=false,n[l]):d(A,n[l],l,f)"}}),Wt=u(Ct,At,{i:"!"+At.i}),Xt=u(Ct,kt,{j:"false",i:kt.i.replace("!","")}),Vt=u(Ct,_t,{q:"if(typeof d=='string'){var v=d;d=function(f){return f[v]}}else if(H)d=o(d,H)",i:{b:"A[l]={a:d(n[l],l,f),b:n[l]}",m:"A"+(St?"[w]=":".push")+"({a:d(n[l],l,f),b:n[l]})"},e:"A.sort(g);p=A.length;while(p--){A[p]=A[p].b}"}),$t=u(Lt,{i:"if(A[l]==null)"+Lt.i}),Jt=u(Lt),Kt=u(Ct,Ot,Mt,{r:i}),Qt=u(Ct,Ot,Mt),Gt=u({a:"t",j:"[]",r:i,i:"if(I.call(n[l])==i)A.push(l)"
|
,St="[object String]",xt=e.clearTimeout,Tt=e.setTimeout,Nt,Ct,kt=n;(function(){function e(){this.x=1}var t=[];e.prototype={valueOf:1,y:1};for(var n in new e)t.push(n);for(n in arguments)kt=!n;Nt=4>(t+"").length,Ct="x"!=t[0]})(1);var Lt=!b(arguments),At="x"!=ft.call("x")[0],Ot="xx"!="x"[0]+Object("x")[0];try{var Mt=("[object Object]",lt.call(e.document||0)==wt)}catch(_t){}var Dt=ct&&/\n|Opera/.test(ct+lt.call(e.opera)),Pt=dt&&/^.+$|true/.test(dt+!!e.attachEvent),Ht={"[object Arguments]":n,"[object Array]"
|
||||||
,e:"A.sort()"});Ft({Arguments:"[object Arguments]",Date:ct,Function:ht,Number:pt,RegExp:dt,String:vt},function(e,t){s["is"+t]=function(t){return it.call(t)==e}}),s.isArguments(arguments)||(s.isArguments=function(e){return!!e&&!!et.call(e,"callee")});var Yt=ot||function(e){return it.call(e)==ft},Zt=u({a:"J",j:"true",q:"var e=I.call(J);if(e==c||e==F)return!J.length",i:{m:"return false"}}),en=at?function(e){return"function"==typeof e&&nt.call(e,"prototype")?Dt(e):at(e)}:Dt,tn=u({a:"t",j:"[]",i:"A.push(n[l])"
|
:n,"[object Boolean]":i,"[object Date]":i,"[object Function]":i,"[object Number]":i,"[object Object]":i,"[object RegExp]":i,"[object String]":n},Bt={"[object Arguments]":i,"[object Array]":n,"[object Boolean]":n,"[object Date]":n,"[object Function]":i,"[object Number]":n,"[object Object]":n,"[object RegExp]":n,"[object String]":n},jt={"&":"&","<":"<",'"':""","'":"'"},Ft={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},It={"\\":"\\","'":"'","\n":"n","\r"
|
||||||
});s.VERSION="0.4.0",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=N,s.bindAll=function(e){var t=arguments,n=1;1==t.length&&(n=0,t=Gt(e));for(var r=t.length;n<r;n++)e[t[n]]=N(e[t[n]],e);return e},s.chain=function(e){return e=new o(e),e._chain=n,e},s.clone=function(e){return e&&Tt[typeof e]?Yt(e)?e.slice():Jt({},e):e},s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)e[n]&&t.push(e[n]);return t},s.compose=function(){var e=
|
:"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var qt={a:"b,a,w",j:"b",q:"if(!a)a=f;else if(w)a=i(a,w)",i:"if(a(y,g,b)===false)return s"},Rt={j:"{}",q:"var o;if(typeof a!='function'){var ii=a;a=function(y){return y[ii]}}else if(w)a=i(a,w)",i:"o=a(y,g,b);(e.call(s,o)?s[o]++:s[o]=1)"},Ut={j:"true",i:"if(!a(y,g,b))return!s"},zt={r:i,s:i,a:"l",j:"l",q:"for(var B=1,C=arguments.length;B<C;B++){if(h=arguments[B]){"
|
||||||
arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=Pt,s.debounce=function(e,t,n){function i(){a=r,n||e.apply(u,s)}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,mt(a),a=gt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=$t,s.defer=function(e){var n=rt.call(arguments,1);return gt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=rt.call(arguments,2);return gt(function(){return e.apply(t,r)},n)},s.difference=function(
|
,i:"s[g]=y",e:"}}"},Wt={j:"[]",i:"a(y,g,b)&&s.push(y)"},Xt={q:"if(w)a=i(a,w)"},Vt={i:{l:qt.i}},$t={j:"",f:"if(!b)return[]",d:{b:"s=Array(j)",l:"s="+(Pt?"Array(j)":"[]")},i:{b:"s[g]=a(y,g,b)",l:"s"+(Pt?"[m]=":".push")+"(a(y,g,b))"}};Lt&&(b=function(e){return!!e&&!!ot.call(e,"callee")});var Jt=ht||function(e){return lt.call(e)==mt};w(/x/)&&(w=function(e){return"[object Function]"==lt.call(e)});var Kt=a({a:"l",j:"[]",i:"s.push(g)"}),Qt=a(zt,{i:"if(s[g]==null)"+zt.i}),Gt=a({r:i,a:"l",j:"{}",q:"var r=c.apply(E,arguments)"
|
||||||
e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=Z.apply(t,arguments);++n<r;)0>w(i,e[n],r)&&t.push(e[n]);return t},s.escape=function(e){return e==r?"":(e+"").replace(J,c)},s.every=Ht,s.extend=Jt,s.filter=Bt,s.find=jt,s.first=y,s.flatten=b,s.forEach=Ft,s.forIn=Kt,s.forOwn=Qt,s.functions=Gt,s.groupBy=It,s.has=function(e,t){return et.call(e,t)},s.identity=k,s.indexOf=w,s.initial=function(e,t,n){return e?rt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;for(var n,
|
,i:"if(N(r,g)<0)s[g]=y"}),Yt=a(zt),Zt=a(qt,Xt,Vt,{r:i}),en=a(qt,Xt,Vt),tn=a({r:i,a:"l",j:"[]",i:"if(T(y))s.push(g)",e:"s.sort()"}),nn=a({a:"y",j:"true",q:"var H=x.call(y),j=y.length;if(D[H]"+(Lt?"||P(y)":"")+"||(H==X&&j>-1&&j===j>>>0&&T(y.splice)))return!j",i:{l:"return false"}}),rn=dt?function(e){var t=typeof e;return"function"==t&&at.call(e,"prototype")?Kt(e):e&&Ft[t]?dt(e):[]}:Kt,sn=a(zt,{a:"l,ee,O,ff",q:"var J,L,Q,gg,dd=O==U;if(!dd)ff=[];for(var B=1,C=dd?2:arguments.length;B<C;B++){if(h=arguments[B]){"
|
||||||
r=-1,i=e.length,s=rt.call(arguments,1);++r<i;)n=e[r],0>w(t,n)&&Ht(s,function(e){return-1<w(e,n)})&&t.push(n);return t},s.invoke=qt,s.isArray=Yt,s.isBoolean=function(e){return e===n||e===i||it.call(e)==lt},s.isElement=function(e){return!!e&&1==e.nodeType},s.isEmpty=Zt,s.isEqual=C,s.isFinite=function(e){return ut(e)&&it.call(e)==pt},s.isNaN=function(e){return it.call(e)==pt&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e&&Tt[typeof e]},s.isUndefined=function(e){return e===
|
,i:"if(y&&((Q=R(y))||U(y))){L=false;gg=ff.length;while(gg--)if(L=ff[gg].c==y)break;if(L){s[g]=ff[gg].d}else{J=(J=s[g])&&Q?(R(J)?J:[]):(U(J)?J:{});ff.push({d:J,c:y});s[g]=G(J,y,U,ff)}}else if(y!=null)s[g]=y"}),on=a({a:"l",j:"[]",i:"s.push(y)"}),un=a({a:"b,hh",j:"false",o:i,d:{b:"if(x.call(h)==v)return b.indexOf(hh)>-1"},i:"if(y===hh)return true"}),an=a(qt,Rt),fn=a(qt,Ut),ln=a(qt,Wt),cn=a(qt,Xt,{j:"",i:"if(a(y,g,b))return y"}),hn=a(qt,Xt),pn=a(qt,Rt,{i:"o=a(y,g,b);(e.call(s,o)?s[o]:s[o]=[]).push(y)"
|
||||||
t},s.keys=en,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:rt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){if(!e)return-1;var r=e.length;for(n&&"number"==typeof n&&(r=(0>n?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.map=Rt,s.max=E,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return et.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=
|
}),dn=a($t,{a:"b,V",q:"var A=u.call(arguments,2),S=typeof V=='function'",i:{b:"s[g]=(S?V:y[V]).apply(y,A)",l:"s"+(Pt?"[m]=":".push")+"((S?V:y[V]).apply(y,A))"}}),vn=a(qt,$t),mn=a($t,{a:"b,bb",i:{b:"s[g]=y[bb]",l:"s"+(Pt?"[m]=":".push")+"(y[bb])"}}),gn=a({a:"b,a,z,w",j:"z",q:"var W=arguments.length<3;if(w)a=i(a,w)",d:{b:"if(W)s=b[++g]"},i:{b:"s=a(s,y,g,b)",l:"s=W?(W=false,y):a(s,y,g,b)"}}),yn=a(qt,Wt,{i:"!"+Wt.i}),bn=a(qt,Ut,{j:"false",i:Ut.i.replace("!","")}),wn=a(qt,Rt,$t,{i:{b:"s[g]={a:a(y,g,b),b:g,d:y}"
|
||||||
e.length;if(!t){for(;++s<o;)e[s]<i&&(i=e[s]);return i}for(n&&(t=h(t,n));++s<o;)n=t(e[s],s,e),n<r&&(r=n,i=e[s]);return i},s.mixin=L,s.noConflict=function(){return e._=j,this},s.once=function(e){var t,r=i;return function(){return r?t:(r=n,t=e.apply(this,arguments))}},s.partial=function(e){var t=rt.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,tt.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=function(e){for(var t,n=0
|
,l:"s"+(Pt?"[m]=":".push")+"({a:a(y,g,b),b:g,d:y})"},e:"s.sort(I);j=s.length;while(j--)s[j]=s[j].d"}),En=a(Wt,{a:"b,aa",q:"var Z,o,q,r=[];K(aa,function(y,o){r.push(o)});var cc=r.length",i:"for(Z=true,q=0;q<cc;q++){o=r[q];if(!(Z=y[o]===aa[o]))break}if(Z)s.push(y)"}),Sn=a({r:i,s:i,a:"l",j:"l",q:"var M=arguments,j=M.length;if(j>1){for(var g=1;g<j;g++)s[M[g]]=F(s[M[g]],s);return s}",i:"if(T(s[g]))s[g]=F(s[g],s)"});s.VERSION="0.5.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply
|
||||||
,r=Z.apply(P,arguments),i=r.length,s={};++n<i;)t=r[n],t in e&&(s[t]=e[t]);return s},s.pluck=Ut,s.range=function(e,t,n){n||(n=1),t==r&&(t=e||0,e=0);for(var i=-1,t=Math.max(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=zt,s.reduceRight=g,s.reject=Wt,s.rest=S,s.result=function(e,t){if(!e)return r;var n=e[t];return it.call(n)==ht?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=Math.floor(Math.random()*(n+1)),i[n]=i[t],i[t]=e[n];return i
|
(this,arguments)}},s.bind=M,s.bindAll=Sn,s.chain=function(e){return e=new o(e),e._chain=n,e},s.clone=E,s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)e[n]&&t.push(e[n]);return t},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=un,s.countBy=an,s.debounce=function(e,t,n){function i(){a=r,n||e.apply(u,s)}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,xt(a),a=Tt
|
||||||
},s.size=function(e){if(!e)return 0;var t=e.length;return t===t>>>0?e.length:en(e).length},s.some=Xt,s.sortBy=Vt,s.sortedIndex=x,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var i,o,u,a,c;i=n.escape,o=n.evaluate,u=n.interpolate;var h=s.templateSettings,n=n.variable;i==r&&(i=h.escape),o==r&&(o=h.evaluate),u==r&&(u=h.interpolate),i&&(e=e.replace(i,d)),u&&(e=e.replace(u,m)),o!=A&&(A=o,_=RegExp((o?o.source:"($^)")+"|<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>","g")),u=Y.length,e=
|
(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=Qt,s.defer=function(e){var n=ft.call(arguments,1);return Tt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=ft.call(arguments,2);return Tt(function(){return e.apply(t,r)},n)},s.difference=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=st.apply(t,arguments),i=u(i,r);++n<r;)i(e[n])||t.push(e[n]);return t},s.drop=Gt,s.escape=function(e){return e==r?"":(e+"").replace(et,h)},s.every=fn,s.extend=Yt,s.filter=ln,s.find=cn,s.first=T,s
|
||||||
e.replace(_,v),i=Y.length-1,o=u<=i,!n&&(n=h.variable||O||"obj",c=o)&&(Y[u]="';__with("+n+"){"+Y[u].replace(I,"").replace(q,"__p+="),Y[i]=Y[i].replace(R,"")+"}____p+='"),h="$&"+n+".",e="__p='"+e.replace(K,l).replace($,f)+"';",Y.length=0,c&&(u=e.indexOf("__with"),i=e.indexOf("}__",u+10)),n!=O&&(O=n,M=RegExp("([(\\s])"+n+"\\."+n+"\\b","g")),e=(c?e.slice(0,u):e).replace(X,h).replace(M,"$1__d")+(c?e.slice(u+2,i+1)+e.slice(i+3).replace(X,h).replace(M,"$1__d"):""),e=(o?e.replace(U,""):e).replace(z,"$1")
|
.flatten=N,s.forEach=hn,s.forIn=Zt,s.forOwn=en,s.functions=tn,s.groupBy=pn,s.has=function(e,t){return e?ot.call(e,t):i},s.identity=_,s.indexOf=C,s.initial=function(e,t,n){return e?ft.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;for(var n,r=-1,i=e.length,s=ft.call(arguments,1),o=[];++r<i;)n=e[r],0>C(t,n)&&fn(s,function(e,t){return(o[t]||(o[t]=u(e)))(n)})&&t.push(n);return t},s.invoke=dn,s.isArguments=b,s.isArray=Jt,s.isBoolean=function(e){return e===n||e===i||lt.
|
||||||
.replace(W,"$1;"),e="function("+n+"){"+n+"||("+n+"={});var __p,__t,__wt,__d="+n+"."+n+"||"+n+",__e=_.escape,__we=__e"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+e+"return __p}";try{a=Function("_","return "+e)(s)}catch(p){a=function(){throw p}}return t?a(t):(a.source=e,a)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e.apply(o,i)):u||(u=gt(n,f
|
call(e)==gt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=nn,s.isEqual=S,s.isFinite=function(e){return pt(e)&<.call(e)==bt},s.isFunction=w,s.isNaN=function(e){return lt.call(e)==bt&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e?Ft[typeof e]:i},s.isUndefined=function(e){return e===t},s.keys=rn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:ft.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){if(!e)return-1;var r=e.length;for(n&&"number"==typeof
|
||||||
)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r<e;)t.call(n,r);else for(;++r<e;)t(r)},s.toArray=function(e){if(!e)return[];if(e.toArray&&it.call(e.toArray)==ht)return e.toArray();var t=e.length;return t===t>>>0?(bt?it.call(e)==vt:"string"==typeof e)?e.split(""):rt.call(e):tn(e)},s.union=function(){for(var e=-1,t=[],n=Z.apply(t,arguments),r=n.length;++e<r;)0>w(t,n[e])&&t.push(n[e]);return t},s.uniq=T,s.uniqueId=function(e){var t=B++;return e?e+t:t},s.values=tn,s.without=function(e){var t=[];
|
n&&(r=(0>n?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.map=vn,s.max=k,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return ot.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=sn,s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]<i&&(i=e[s]);return i}for(n&&(t=d(t,n));++s<o;)n=t(e[s],s,e),n<r&&(r=n,i=e[s]);return i},s.mixin=D,s.noConflict=function(){return e._=X,this
|
||||||
if(!e)return t;for(var n=-1,r=e.length;++n<r;)0>w(arguments,e[n],1)&&t.push(e[n]);return t},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&tt.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=E(Ut(arguments,"length")),r=Array(n);++t<n;)r[t]=Ut(arguments,t);return r},s.zipObject=function(e,t){if(!e)return{};var n=-1,r=e.length,i={};for(t||(t=[]);++n<r;)i[e[n]]=t[n];return i},s.all=Ht,s.any=Xt,s.collect=Rt,s.detect=jt,s.each=Ft,s.foldl=zt
|
},s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.partial=function(e){var t=ft.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,ut.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=function(e){var t={};if(!e)return t;for(var n,r=0,i=st.apply(I,arguments),s=i.length;++r<s;)n=i[r],n in e&&(t[n]=e[n]);return t},s.pluck=mn,s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,
|
||||||
,s.foldr=g,s.head=y,s.include=Pt,s.inject=zt,s.methods=Gt,s.select=Bt,s.tail=S,s.take=y,s.unique=T,o.prototype=s.prototype,L(s),o.prototype.chain=function(){return this._chain=n,this},o.prototype.value=function(){return this._wrapped},Ft("pop push reverse shift sort splice unshift".split(" "),function(e){var t=P[e];o.prototype[e]=function(){var e=this._wrapped;return t.apply(e,arguments),e.length===0&&delete e[0],this._chain&&(e=new o(e),e._chain=n),e}}),Ft(["concat","join","slice"],function(e){var t=
|
e=0);for(var i=-1,t=Math.max(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=gn,s.reduceRight=x,s.reject=yn,s.rest=L,s.result=function(e,t){if(!e)return r;var n=e[t];return w(n)?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=Math.floor(Math.random()*(n+1)),i[n]=i[t],i[t]=e[n];return i},s.size=function(e){if(!e)return 0;var t=lt.call(e),n=e.length;return Ht[t]||Lt&&b(e)||t==wt&&-1<n&&n===n>>>0&&w(e.splice)?n:rn(e).length},s.some=
|
||||||
P[e];o.prototype[e]=function(){var e=t.apply(this._wrapped,arguments);return this._chain&&(e=new o(e),e._chain=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):D?"object"==typeof module&&module&&module.s==D?(module.s=s)._=s:D._=s:e._=s})(this);
|
bn,s.sortBy=wn,s.sortedIndex=A,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var e=e+"",o,u;o=n.escape;var a=n.evaluate,f=n.interpolate,h=s.templateSettings,p=n=n.variable||h.variable;o==r&&(o=h.escape),a==r&&(a=h.evaluate||i),f==r&&(f=h.interpolate),o&&(e=e.replace(o,m)),f&&(e=e.replace(f,y)),a!=P&&(P=a,j=RegExp("<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>"+(a?"|"+a.source:""),"g")),o=it.length,e=e.replace(j,g),o=o!=it.length,e="__p += '"+e.replace(tt,c).replace(Z,l)+"';",it.
|
||||||
|
length=0,p||(n=H||"obj",o?e="with("+n+"){"+e+"}":(n!=H&&(H=n,B=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(G,"$&"+n+".").replace(B,"$1__d"))),e=(o?e.replace($,""):e).replace(J,"$1").replace(K,"$1;"),e="function("+n+"){"+(p?"":n+"||("+n+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(p?"":",__d="+n+"."+n+"||"+n)+";")+e+"return __p}";try{u=Function("_","return "+e)(s)}catch(d){u=function(){throw d}}return t?u(t):(u.source=
|
||||||
|
e,u)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e.apply(o,i)):u||(u=Tt(n,f)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r<e;)t.call(n,r);else for(;++r<e;)t(r)},s.toArray=function(e){if(!e)return[];if(e.toArray&&w(e.toArray))return e.toArray();var t=e.length;return-1<t&&t===t>>>0?(At?lt.call(e)==St:"string"==typeof e)?e.split(""):ft.call(e):on(e)},s.union=function(){for(var e=-1
|
||||||
|
,t=[],n=st.apply(t,arguments),r=n.length;++e<r;)0>C(t,n[e])&&t.push(n[e]);return t},s.uniq=O,s.uniqueId=function(e){var t=W++;return e?e+t:t},s.values=on,s.where=En,s.without=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=u(arguments,1,20);++n<r;)i(e[n])||t.push(e[n]);return t},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&ut.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=k(mn(arguments,"length")),r=Array(n);++t<n;)r
|
||||||
|
[t]=mn(arguments,t);return r},s.zipObject=function(e,t){if(!e)return{};var n=-1,r=e.length,i={};for(t||(t=[]);++n<r;)i[e[n]]=t[n];return i},s.all=fn,s.any=bn,s.collect=vn,s.detect=cn,s.each=hn,s.foldl=gn,s.foldr=x,s.head=T,s.include=un,s.inject=gn,s.methods=tn,s.select=ln,s.tail=L,s.take=T,s.unique=O,hn({Date:yt,Number:bt,RegExp:Et,String:St},function(e,t){s["is"+t]=function(t){return lt.call(t)==e}}),o.prototype=s.prototype,D(s),o.prototype.chain=function(){return this._chain=n,this},o.prototype
|
||||||
|
.value=function(){return this._wrapped},hn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=I[e];o.prototype[e]=function(){var e=this._wrapped;return t.apply(e,arguments),e.length===0&&delete e[0],this._chain&&(e=new o(e),e._chain=n),e}}),hn(["concat","join","slice"],function(e){var t=I[e];o.prototype[e]=function(){var e=t.apply(this._wrapped,arguments);return this._chain&&(e=new o(e),e._chain=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=
|
||||||
|
s,define(function(){return s})):F?"object"==typeof module&&module&&module.t==F?(module.t=s)._=s:F._=s:e._=s})(this);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "lodash",
|
"name": "lodash",
|
||||||
"version": "0.4.0",
|
"version": "0.5.2",
|
||||||
"description": "A drop-in replacement for Underscore.js that delivers performance improvements, bug fixes, and additional features.",
|
"description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.",
|
||||||
"homepage": "http://lodash.com",
|
"homepage": "http://lodash.com",
|
||||||
"main": "lodash",
|
"main": "lodash",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
],
|
],
|
||||||
"author": {
|
"author": {
|
||||||
"name": "John-David Dalton",
|
"name": "John-David Dalton",
|
||||||
"email": "john@fusejs.com",
|
"email": "john.david.dalton@gmail.com",
|
||||||
"web": "http://allyoucanleet.com/"
|
"web": "http://allyoucanleet.com/"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@@ -42,6 +42,9 @@
|
|||||||
"node",
|
"node",
|
||||||
"rhino"
|
"rhino"
|
||||||
],
|
],
|
||||||
|
"jam": {
|
||||||
|
"main": "lodash.min.js"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build",
|
"build": "node build",
|
||||||
"test": "node test/test"
|
"test": "node test/test"
|
||||||
|
|||||||
@@ -20,29 +20,40 @@
|
|||||||
<script>
|
<script>
|
||||||
var lodash = _.noConflict();
|
var lodash = _.noConflict();
|
||||||
</script>
|
</script>
|
||||||
<script src="../vendor/underscore/underscore.js"></script>
|
<script src="../vendor/underscore/underscore-min.js"></script>
|
||||||
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script src="../vendor/benchmark.js/benchmark.js"></script>
|
<script src="../vendor/benchmark.js/benchmark.js"></script>
|
||||||
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
|
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
|
||||||
|
<script src="perf.js"></script>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
|
var measured,
|
||||||
// using innerHTML avoids an alert in some versions of IE6
|
perfNow,
|
||||||
var div = document.createElement('div');
|
begin = new Date;
|
||||||
div.innerHTML = '<applet code=nano archive="../vendor/benchmark.js/nano.jar">';
|
|
||||||
document.body.insertBefore(div.lastChild, document.body.firstChild);
|
function init() {
|
||||||
|
var fbUI = document.getElementById('FirebugUI'),
|
||||||
|
fbDoc = fbUI && (fbDoc = fbUI.contentWindow || fbUI.contentDocument).document || fbDoc,
|
||||||
|
fbCommandLine = fbDoc && fbDoc.getElementById('fbCommandLine');
|
||||||
|
|
||||||
|
if (!fbCommandLine) {
|
||||||
|
return setTimeout(init, 15);
|
||||||
|
}
|
||||||
|
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
|
||||||
|
setTimeout(run, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is the applet permitted?
|
||||||
|
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
|
||||||
|
// is the applet really needed?
|
||||||
|
while (!(measured = new Date - begin)) { }
|
||||||
|
if (measured != 1 && !((perfNow = window.performance) && typeof (perfNow.now || perfNow.webkitNow) == 'function')) {
|
||||||
|
// load applet
|
||||||
|
document.write('<applet code="nano" archive="../vendor/benchmark.js/nano.jar"></applet>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.onload = init;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
var fbUI = document.getElementById('FirebugUI'),
|
|
||||||
fbDoc = (fbDoc = fbUI.contentWindow || fbUI.contentDocument).document || fbDoc,
|
|
||||||
sibling = document.getElementsByTagName('script')[0],
|
|
||||||
script = document.createElement('script');
|
|
||||||
|
|
||||||
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
|
|
||||||
script.src = 'perf.js?t=' + (+new Date);
|
|
||||||
sibling.parentNode.insertBefore(script, sibling);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
1564
perf/perf.js
1564
perf/perf.js
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,14 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="qunit"></div>
|
<div id="qunit"></div>
|
||||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
|
<script>
|
||||||
|
// avoid syntax errors for `QUnit.throws` in older Firefoxes
|
||||||
|
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
|
||||||
|
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
|
||||||
|
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
|
||||||
|
);
|
||||||
|
</script>
|
||||||
<script src="test-ui.js"></script>
|
<script src="test-ui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// set a bad shim
|
// set a bad shim
|
||||||
@@ -59,6 +66,17 @@
|
|||||||
|
|
||||||
require(['test.js']);
|
require(['test.js']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// set a more readable browser name
|
||||||
|
window.onload = function() {
|
||||||
|
var timeoutId = setInterval(function() {
|
||||||
|
var ua = document.getElementById('qunit-userAgent');
|
||||||
|
if (ua) {
|
||||||
|
ua.innerHTML = platform;
|
||||||
|
clearInterval(timeoutId);
|
||||||
|
}
|
||||||
|
}, 15);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -45,10 +45,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
var header = document.getElementById('qunit-header');
|
var toolbar = document.getElementById('qunit-testrunner-toolbar');
|
||||||
if (header) {
|
if (toolbar) {
|
||||||
header.appendChild(label1);
|
toolbar.appendChild(label1);
|
||||||
header.appendChild(label2);
|
toolbar.appendChild(label2);
|
||||||
|
|
||||||
dropdown.selectedIndex = (function() {
|
dropdown.selectedIndex = (function() {
|
||||||
switch (build) {
|
switch (build) {
|
||||||
@@ -70,19 +70,19 @@
|
|||||||
|
|
||||||
var label1 = document.createElement('label');
|
var label1 = document.createElement('label');
|
||||||
label1.innerHTML =
|
label1.innerHTML =
|
||||||
'<input name="norequire" type="checkbox">norequire</label>';
|
'<input name="norequire" type="checkbox">No RequireJS';
|
||||||
|
|
||||||
var label2 = document.createElement('label');
|
var label2 = document.createElement('label');
|
||||||
label2.innerHTML =
|
label2.innerHTML = ' ' +
|
||||||
'<select name="build">' +
|
'<select name="build">' +
|
||||||
'<option value="dev">developement</option>' +
|
'<option value="dev">Developement</option>' +
|
||||||
'<option value="prod">production</option>' +
|
'<option value="prod">Production</option>' +
|
||||||
'<option value="custom">custom</option>' +
|
'<option value="custom">Custom</option>' +
|
||||||
'<option value="custom-debug">custom (debug)</option>' +
|
'<option value="custom-debug">Custom (debug)</option>' +
|
||||||
'</select>build';
|
'</select> Build';
|
||||||
|
|
||||||
var checkbox = label1.firstChild,
|
var checkbox = label1.firstChild,
|
||||||
dropdown = label2.firstChild;
|
dropdown = label2.getElementsByTagName('select')[0];
|
||||||
|
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
|
|||||||
861
test/test.js
861
test/test.js
File diff suppressed because it is too large
Load Diff
83
vendor/backbone/backbone.js
vendored
83
vendor/backbone/backbone.js
vendored
@@ -134,6 +134,9 @@
|
|||||||
|
|
||||||
rest = [];
|
rest = [];
|
||||||
events = events.split(eventSplitter);
|
events = events.split(eventSplitter);
|
||||||
|
|
||||||
|
// Fill up `rest` with the callback arguments. Since we're only copying
|
||||||
|
// the tail of `arguments`, a loop is much faster than Array#slice.
|
||||||
for (i = 1, length = arguments.length; i < length; i++) {
|
for (i = 1, length = arguments.length; i < length; i++) {
|
||||||
rest[i - 1] = arguments[i];
|
rest[i - 1] = arguments[i];
|
||||||
}
|
}
|
||||||
@@ -295,7 +298,7 @@
|
|||||||
|
|
||||||
// If the new and previous value differ, record the change. If not,
|
// If the new and previous value differ, record the change. If not,
|
||||||
// then remove changes for this attribute.
|
// then remove changes for this attribute.
|
||||||
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
|
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) !== _.has(prev, attr))) {
|
||||||
this.changed[attr] = val;
|
this.changed[attr] = val;
|
||||||
if (!options.silent) this._pending[attr] = true;
|
if (!options.silent) this._pending[attr] = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -432,7 +435,7 @@
|
|||||||
url: function() {
|
url: function() {
|
||||||
var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
|
var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
|
||||||
if (this.isNew()) return base;
|
if (this.isNew()) return base;
|
||||||
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
|
return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
// **parse** converts a response into the hash of attributes to be `set` on
|
// **parse** converts a response into the hash of attributes to be `set` on
|
||||||
@@ -555,10 +558,13 @@
|
|||||||
var Collection = Backbone.Collection = function(models, options) {
|
var Collection = Backbone.Collection = function(models, options) {
|
||||||
options || (options = {});
|
options || (options = {});
|
||||||
if (options.model) this.model = options.model;
|
if (options.model) this.model = options.model;
|
||||||
if (options.comparator !== undefined) this.comparator = options.comparator;
|
if (options.comparator !== void 0) this.comparator = options.comparator;
|
||||||
this._reset();
|
this._reset();
|
||||||
this.initialize.apply(this, arguments);
|
this.initialize.apply(this, arguments);
|
||||||
if (models) this.reset(models, {silent: true, parse: options.parse});
|
if (models) {
|
||||||
|
if (options.parse) models = this.parse(models);
|
||||||
|
this.reset(models, {silent: true, parse: options.parse});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define the Collection's inheritable methods.
|
// Define the Collection's inheritable methods.
|
||||||
@@ -628,9 +634,7 @@
|
|||||||
// Merge in duplicate models.
|
// Merge in duplicate models.
|
||||||
if (options.merge) {
|
if (options.merge) {
|
||||||
for (i = 0, length = dups.length; i < length; i++) {
|
for (i = 0, length = dups.length; i < length; i++) {
|
||||||
if (model = this._byId[dups[i].id]) {
|
if (model = this._byId[dups[i].id]) model.set(dups[i], options);
|
||||||
model.set(dups[i], options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,7 +741,7 @@
|
|||||||
options || (options = {});
|
options || (options = {});
|
||||||
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
|
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
|
||||||
var boundComparator = _.bind(this.comparator, this);
|
var boundComparator = _.bind(this.comparator, this);
|
||||||
if (this.comparator.length == 1) {
|
if (this.comparator.length === 1) {
|
||||||
this.models = this.sortBy(boundComparator);
|
this.models = this.sortBy(boundComparator);
|
||||||
} else {
|
} else {
|
||||||
this.models.sort(boundComparator);
|
this.models.sort(boundComparator);
|
||||||
@@ -771,7 +775,7 @@
|
|||||||
// models to the collection instead of resetting.
|
// models to the collection instead of resetting.
|
||||||
fetch: function(options) {
|
fetch: function(options) {
|
||||||
options = options ? _.clone(options) : {};
|
options = options ? _.clone(options) : {};
|
||||||
if (options.parse === undefined) options.parse = true;
|
if (options.parse === void 0) options.parse = true;
|
||||||
var collection = this;
|
var collection = this;
|
||||||
var success = options.success;
|
var success = options.success;
|
||||||
options.success = function(resp, status, xhr) {
|
options.success = function(resp, status, xhr) {
|
||||||
@@ -842,9 +846,7 @@
|
|||||||
|
|
||||||
// Internal method to remove a model's ties to a collection.
|
// Internal method to remove a model's ties to a collection.
|
||||||
_removeReference: function(model) {
|
_removeReference: function(model) {
|
||||||
if (this == model.collection) {
|
if (this === model.collection) delete model.collection;
|
||||||
delete model.collection;
|
|
||||||
}
|
|
||||||
model.off('all', this._onModelEvent, this);
|
model.off('all', this._onModelEvent, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -853,10 +855,8 @@
|
|||||||
// events simply proxy through. "add" and "remove" events that originate
|
// events simply proxy through. "add" and "remove" events that originate
|
||||||
// in other collections are ignored.
|
// in other collections are ignored.
|
||||||
_onModelEvent: function(event, model, collection, options) {
|
_onModelEvent: function(event, model, collection, options) {
|
||||||
if ((event == 'add' || event == 'remove') && collection != this) return;
|
if ((event === 'add' || event === 'remove') && collection !== this) return;
|
||||||
if (event == 'destroy') {
|
if (event === 'destroy') this.remove(model, options);
|
||||||
this.remove(model, options);
|
|
||||||
}
|
|
||||||
if (model && event === 'change:' + model.idAttribute) {
|
if (model && event === 'change:' + model.idAttribute) {
|
||||||
delete this._byId[model.previous(model.idAttribute)];
|
delete this._byId[model.previous(model.idAttribute)];
|
||||||
if (model.id != null) this._byId[model.id] = model;
|
if (model.id != null) this._byId[model.id] = model;
|
||||||
@@ -867,11 +867,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Underscore methods that we want to implement on the Collection.
|
// Underscore methods that we want to implement on the Collection.
|
||||||
var methods = ['forEach', 'each', 'map', 'reduce', 'reduceRight', 'find',
|
var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
|
||||||
'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any',
|
'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
|
||||||
'include', 'contains', 'invoke', 'max', 'min', 'sortBy', 'sortedIndex',
|
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
|
||||||
'toArray', 'size', 'first', 'initial', 'rest', 'last', 'without', 'indexOf',
|
'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size', 'first', 'head',
|
||||||
'shuffle', 'lastIndexOf', 'isEmpty', 'groupBy'];
|
'take', 'initial', 'rest', 'tail', 'last', 'without', 'indexOf', 'shuffle',
|
||||||
|
'lastIndexOf', 'isEmpty', 'groupBy'];
|
||||||
|
|
||||||
// Mix in each Underscore method as a proxy to `Collection#models`.
|
// Mix in each Underscore method as a proxy to `Collection#models`.
|
||||||
_.each(methods, function(method) {
|
_.each(methods, function(method) {
|
||||||
@@ -1029,6 +1030,9 @@
|
|||||||
var docMode = document.documentMode;
|
var docMode = document.documentMode;
|
||||||
var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
|
var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
|
||||||
|
|
||||||
|
// Normalize root to always include trailing slash
|
||||||
|
if (!trailingSlash.test(this.options.root)) this.options.root += '/';
|
||||||
|
|
||||||
if (oldIE && this._wantsHashChange) {
|
if (oldIE && this._wantsHashChange) {
|
||||||
this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
|
this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
|
||||||
this.navigate(fragment);
|
this.navigate(fragment);
|
||||||
@@ -1048,7 +1052,7 @@
|
|||||||
// opened by a non-pushState browser.
|
// opened by a non-pushState browser.
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
var loc = this.location;
|
var loc = this.location;
|
||||||
var atRoot = (loc.pathname == this.options.root) && !loc.search;
|
var atRoot = (loc.pathname.replace(/[^/]$/, '$&/') === this.options.root) && !loc.search;
|
||||||
|
|
||||||
// If we've started off with a route from a `pushState`-enabled browser,
|
// 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...
|
// but we're currently in a browser that doesn't support it...
|
||||||
@@ -1065,9 +1069,7 @@
|
|||||||
this.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
|
this.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.options.silent) {
|
if (!this.options.silent) return this.loadUrl();
|
||||||
return this.loadUrl();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Disable Backbone.history, perhaps temporarily. Not useful in a real app,
|
// Disable Backbone.history, perhaps temporarily. Not useful in a real app,
|
||||||
@@ -1088,10 +1090,10 @@
|
|||||||
// calls `loadUrl`, normalizing across the hidden iframe.
|
// calls `loadUrl`, normalizing across the hidden iframe.
|
||||||
checkUrl: function(e) {
|
checkUrl: function(e) {
|
||||||
var current = this.getFragment();
|
var current = this.getFragment();
|
||||||
if (current == this.fragment && this.iframe) {
|
if (current === this.fragment && this.iframe) {
|
||||||
current = this.getFragment(this.getHash(this.iframe));
|
current = this.getFragment(this.getHash(this.iframe));
|
||||||
}
|
}
|
||||||
if (current == this.fragment) return false;
|
if (current === this.fragment) return false;
|
||||||
if (this.iframe) this.navigate(current);
|
if (this.iframe) this.navigate(current);
|
||||||
this.loadUrl() || this.loadUrl(this.getHash());
|
this.loadUrl() || this.loadUrl(this.getHash());
|
||||||
},
|
},
|
||||||
@@ -1121,9 +1123,9 @@
|
|||||||
if (!History.started) return false;
|
if (!History.started) return false;
|
||||||
if (!options || options === true) options = {trigger: options};
|
if (!options || options === true) options = {trigger: options};
|
||||||
var frag = (fragment || '').replace(routeStripper, '');
|
var frag = (fragment || '').replace(routeStripper, '');
|
||||||
if (this.fragment == frag) return;
|
if (this.fragment === frag) return;
|
||||||
this.fragment = frag;
|
this.fragment = frag;
|
||||||
var url = (frag.indexOf(this.options.root) != 0 ? this.options.root : '') + frag;
|
var url = (frag.indexOf(this.options.root) !== 0 ? this.options.root : '') + frag;
|
||||||
|
|
||||||
// If pushState is available, we use it to set the fragment as a real URL.
|
// If pushState is available, we use it to set the fragment as a real URL.
|
||||||
if (this._hasPushState) {
|
if (this._hasPushState) {
|
||||||
@@ -1133,7 +1135,7 @@
|
|||||||
// fragment to store history.
|
// fragment to store history.
|
||||||
} else if (this._wantsHashChange) {
|
} else if (this._wantsHashChange) {
|
||||||
this._updateHash(this.location, frag, options.replace);
|
this._updateHash(this.location, frag, options.replace);
|
||||||
if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) {
|
if (this.iframe && (frag !== this.getFragment(this.getHash(this.iframe)))) {
|
||||||
// Opening and closing the iframe tricks IE7 and earlier to push a
|
// Opening and closing the iframe tricks IE7 and earlier to push a
|
||||||
// history entry on hash-tag change. When replace is true, we don't
|
// history entry on hash-tag change. When replace is true, we don't
|
||||||
// want this.
|
// want this.
|
||||||
@@ -1158,6 +1160,7 @@
|
|||||||
location.hash = fragment;
|
location.hash = fragment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Backbone.View
|
// Backbone.View
|
||||||
@@ -1202,9 +1205,19 @@
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Clean up references to this view in order to prevent latent effects and
|
||||||
|
// memory leaks.
|
||||||
|
dispose: function() {
|
||||||
|
this.undelegateEvents();
|
||||||
|
if (this.model) this.model.off(null, null, this);
|
||||||
|
if (this.collection) this.collection.off(null, null, this);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
// Remove this view from the DOM. Note that the view isn't present in the
|
// Remove this view from the DOM. Note that the view isn't present in the
|
||||||
// DOM by default, so calling this method may be a no-op.
|
// DOM by default, so calling this method may be a no-op.
|
||||||
remove: function() {
|
remove: function() {
|
||||||
|
this.dispose();
|
||||||
this.$el.remove();
|
this.$el.remove();
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
@@ -1291,8 +1304,8 @@
|
|||||||
_ensureElement: function() {
|
_ensureElement: function() {
|
||||||
if (!this.el) {
|
if (!this.el) {
|
||||||
var attrs = _.extend({}, getValue(this, 'attributes'));
|
var attrs = _.extend({}, getValue(this, 'attributes'));
|
||||||
if (this.id) attrs.id = this.id;
|
if (this.id) attrs.id = getValue(this, 'id');
|
||||||
if (this.className) attrs['class'] = this.className;
|
if (this.className) attrs['class'] = getValue(this, 'className');
|
||||||
this.setElement(this.make(getValue(this, 'tagName'), attrs), false);
|
this.setElement(this.make(getValue(this, 'tagName'), attrs), false);
|
||||||
} else {
|
} else {
|
||||||
this.setElement(this.el, false);
|
this.setElement(this.el, false);
|
||||||
@@ -1303,9 +1316,7 @@
|
|||||||
|
|
||||||
// The self-propagating extend function that Backbone classes use.
|
// The self-propagating extend function that Backbone classes use.
|
||||||
var extend = function(protoProps, classProps) {
|
var extend = function(protoProps, classProps) {
|
||||||
var child = inherits(this, protoProps, classProps);
|
return inherits(this, protoProps, classProps);
|
||||||
child.extend = this.extend;
|
|
||||||
return child;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up inheritance for the model, collection, and view.
|
// Set up inheritance for the model, collection, and view.
|
||||||
@@ -1352,7 +1363,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that we have the appropriate request data.
|
// Ensure that we have the appropriate request data.
|
||||||
if (!options.data && model && (method == 'create' || method == 'update')) {
|
if (!options.data && model && (method === 'create' || method === 'update')) {
|
||||||
params.contentType = 'application/json';
|
params.contentType = 'application/json';
|
||||||
params.data = JSON.stringify(model);
|
params.data = JSON.stringify(model);
|
||||||
}
|
}
|
||||||
|
|||||||
23
vendor/backbone/test/collection.js
vendored
23
vendor/backbone/test/collection.js
vendored
@@ -47,6 +47,29 @@ $(document).ready(function() {
|
|||||||
equal(col.length, 4);
|
equal(col.length, 4);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Collection: new and parse", 3, function() {
|
||||||
|
var MyCol = Backbone.Collection.extend({
|
||||||
|
// only save the models that have an even value.
|
||||||
|
parse : function(data) {
|
||||||
|
var onlyEven = [];
|
||||||
|
_.each(data, function(datum) {
|
||||||
|
if (datum.a % 2 === 0) {
|
||||||
|
onlyEven.push(datum);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return onlyEven;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
anotherCol = new MyCol([
|
||||||
|
{ a : 1 },{ a : 2 },{ a : 3 },{ a : 4 }
|
||||||
|
], { parse : true });
|
||||||
|
|
||||||
|
equal(anotherCol.length, 2);
|
||||||
|
equal(anotherCol.first().get('a'), 2)
|
||||||
|
equal(anotherCol.last().get('a'), 4);
|
||||||
|
});
|
||||||
|
|
||||||
test("Collection: get, getByCid", 3, function() {
|
test("Collection: get, getByCid", 3, function() {
|
||||||
equal(col.get(0), d);
|
equal(col.get(0), d);
|
||||||
equal(col.get(2), b);
|
equal(col.get(2), b);
|
||||||
|
|||||||
52
vendor/backbone/test/router.js
vendored
52
vendor/backbone/test/router.js
vendored
@@ -20,9 +20,11 @@ $(document).ready(function() {
|
|||||||
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
||||||
'href',
|
'href',
|
||||||
'hash',
|
'hash',
|
||||||
|
'host',
|
||||||
'search',
|
'search',
|
||||||
'fragment',
|
'fragment',
|
||||||
'pathname'
|
'pathname',
|
||||||
|
'protocol'
|
||||||
));
|
));
|
||||||
// In IE, anchor.pathname does not contain a leading slash though
|
// In IE, anchor.pathname does not contain a leading slash though
|
||||||
// window.location.pathname does.
|
// window.location.pathname does.
|
||||||
@@ -318,4 +320,52 @@ $(document).ready(function() {
|
|||||||
strictEqual(Backbone.history.fragment, 'x');
|
strictEqual(Backbone.history.fragment, 'x');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Router: Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = new Backbone.History({
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {
|
||||||
|
strictEqual(url, '/root/fragment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root',
|
||||||
|
hashChange: false
|
||||||
|
});
|
||||||
|
Backbone.history.navigate('fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root#fragment');
|
||||||
|
Backbone.history = new Backbone.History({
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {},
|
||||||
|
replaceState: function(state, title, url) {
|
||||||
|
strictEqual(url, 'http://example.com/root/fragment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Router: Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = new Backbone.History({location: location});
|
||||||
|
Backbone.history.loadUrl = function() { ok(true); };
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
38
vendor/backbone/test/view.js
vendored
38
vendor/backbone/test/view.js
vendored
@@ -135,6 +135,20 @@ $(document).ready(function() {
|
|||||||
ok(!view.el);
|
ok(!view.el);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("View: with className and id functions", 2, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
className: function() {
|
||||||
|
return 'className';
|
||||||
|
},
|
||||||
|
id: function() {
|
||||||
|
return 'id';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var view = new View();
|
||||||
|
strictEqual(view.el.className, 'className');
|
||||||
|
strictEqual(view.el.id, 'id');
|
||||||
|
});
|
||||||
|
|
||||||
test("View: with attributes", 2, function() {
|
test("View: with attributes", 2, function() {
|
||||||
var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
|
var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
|
||||||
equal(view.el.className, 'one');
|
equal(view.el.className, 'one');
|
||||||
@@ -227,4 +241,28 @@ $(document).ready(function() {
|
|||||||
ok(new View().$el.is('p'));
|
ok(new View().$el.is('p'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("dispose", 0, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
events: {click: function(){ ok(false); }},
|
||||||
|
initialize: function() {
|
||||||
|
this.model.on('all x', function(){ ok(false); }, this);
|
||||||
|
this.collection.on('all x', function(){ ok(false); }, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var view = new View({
|
||||||
|
model: new Backbone.Model,
|
||||||
|
collection: new Backbone.Collection
|
||||||
|
});
|
||||||
|
view.dispose();
|
||||||
|
view.model.trigger('x');
|
||||||
|
view.collection.trigger('x');
|
||||||
|
view.$el.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("view#remove calls dispose.", 1, function() {
|
||||||
|
var view = new Backbone.View();
|
||||||
|
view.dispose = function() { ok(true); };
|
||||||
|
view.remove();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
57
vendor/benchmark.js/README.md
vendored
57
vendor/benchmark.js/README.md
vendored
@@ -1,30 +1,34 @@
|
|||||||
# Benchmark.js <sup>v1.0.0-pre</sup>
|
# Benchmark.js <sup>v1.0.0</sup>
|
||||||
|
|
||||||
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/).
|
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/).
|
||||||
|
|
||||||
## BestieJS
|
## Download
|
||||||
|
|
||||||
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.
|
* [Development source](https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js)
|
||||||
|
|
||||||
## Documentation
|
## Dive in
|
||||||
|
|
||||||
The documentation for Benchmark.js can be viewed here: <http://benchmarkjs.com/docs>
|
We’ve 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).
|
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 Adobe AIR 3.1, Chrome 5-21, Firefox 1.5-13, IE 6-9, Opera 9.25-12.01, Safari 3-6, Node.js 0.8.7, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||||
|
|
||||||
## Installation and usage
|
## Installation and usage
|
||||||
|
|
||||||
In a browser or Adobe AIR:
|
In a browser or Adobe AIR:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<script src="benchmark.js"></script>
|
<script src="benchmark.js"></script>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<applet code="nano" archive="nano.jar"></applet>
|
<applet code="nano" archive="nano.jar"></applet>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
|
Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
|
||||||
|
|
||||||
@@ -32,37 +36,37 @@ Or enable Chrome’s microsecond timer by using the [command line switch](http:/
|
|||||||
|
|
||||||
Via [npm](http://npmjs.org/):
|
Via [npm](http://npmjs.org/):
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install benchmark
|
npm install benchmark
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var Benchmark = require('benchmark');
|
var Benchmark = require('benchmark');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install microtime
|
npm install microtime
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var Benchmark = require('benchmark').Benchmark;
|
var Benchmark = require('benchmark').Benchmark;
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Rhino](http://www.mozilla.org/rhino/):
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
load('benchmark.js');
|
load('benchmark.js');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
require({
|
require({
|
||||||
'paths': {
|
'paths': {
|
||||||
'benchmark': 'path/to/benchmark'
|
'benchmark': 'path/to/benchmark'
|
||||||
@@ -84,11 +88,11 @@ require({
|
|||||||
Benchmark.platform = platform;
|
Benchmark.platform = platform;
|
||||||
console.log(Benchmark.platform.name);
|
console.log(Benchmark.platform.name);
|
||||||
});
|
});
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var suite = new Benchmark.Suite;
|
var suite = new Benchmark.Suite;
|
||||||
|
|
||||||
// add tests
|
// add tests
|
||||||
@@ -112,12 +116,11 @@ suite.add('RegExp#test', function() {
|
|||||||
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
||||||
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
||||||
// > Fastest is String#indexOf
|
// > Fastest is String#indexOf
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Footnotes
|
## BestieJS
|
||||||
|
|
||||||
1. Benchmark.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3.
|
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.
|
||||||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
|
|||||||
266
vendor/benchmark.js/benchmark.js
vendored
266
vendor/benchmark.js/benchmark.js
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
* Benchmark.js v1.0.0-pre <http://benchmarkjs.com/>
|
* Benchmark.js v1.0.0 <http://benchmarkjs.com/>
|
||||||
* Copyright 2010-2012 Mathias Bynens <http://mths.be/>
|
* Copyright 2010-2012 Mathias Bynens <http://mths.be/>
|
||||||
* Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
* Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
||||||
* Modified by John-David Dalton <http://allyoucanleet.com/>
|
* Modified by John-David Dalton <http://allyoucanleet.com/>
|
||||||
@@ -244,6 +244,36 @@
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
support.getAllKeys = false;
|
support.getAllKeys = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if own properties are iterated before inherited properties (all but IE < 9).
|
||||||
|
*
|
||||||
|
* @name iteratesOwnLast
|
||||||
|
* @memberOf Benchmark.support
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
support.iteratesOwnFirst = (function() {
|
||||||
|
var props = [];
|
||||||
|
function ctor() { this.x = 1; }
|
||||||
|
ctor.prototype = { 'y': 1 };
|
||||||
|
for (var prop in new ctor) { props.push(prop); }
|
||||||
|
return props[0] == 'x';
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if a node's [[Class]] is resolvable (all but IE < 9)
|
||||||
|
* and that the JS engine errors when attempting to coerce an object to a
|
||||||
|
* string without a `toString` property value of `typeof` "function".
|
||||||
|
*
|
||||||
|
* @name nodeClass
|
||||||
|
* @memberOf Benchmark.support
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
support.nodeClass = ({ 'toString': 0 } + '', toString.call(doc || 0) != '[object Object]');
|
||||||
|
} catch(e) {
|
||||||
|
support.nodeClass = true;
|
||||||
|
}
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -583,14 +613,17 @@
|
|||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
if ((index - start) in tail) {
|
if ((index - start) in tail) {
|
||||||
object[index] = tail[index - start];
|
object[index] = tail[index - start];
|
||||||
} else {
|
} else if (index in object) {
|
||||||
delete object[index];
|
delete object[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// delete excess elements
|
// delete excess elements
|
||||||
deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
|
deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
|
||||||
while (deleteCount--) {
|
while (deleteCount--) {
|
||||||
delete object[length + deleteCount];
|
index = length + deleteCount;
|
||||||
|
if (index in object) {
|
||||||
|
delete object[index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
object.length = length;
|
object.length = length;
|
||||||
return result;
|
return result;
|
||||||
@@ -941,7 +974,13 @@
|
|||||||
// escape the `{` for Firefox 1
|
// escape the `{` for Firefox 1
|
||||||
result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
|
result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
|
||||||
}
|
}
|
||||||
return (result || '').replace(/^\s+|\s+$/g, '');
|
// trim string
|
||||||
|
result = (result || '').replace(/^\s+|\s+$/g, '');
|
||||||
|
|
||||||
|
// detect strings containing only the "use strict" directive
|
||||||
|
return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
|
||||||
|
? ''
|
||||||
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -994,36 +1033,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the specified `value` is an object created by the `Object`
|
* Checks if a given `value` is an object created by the `Object` constructor
|
||||||
* constructor assuming objects created by the `Object` constructor have no
|
* assuming objects created by the `Object` constructor have no inherited
|
||||||
* inherited enumerable properties and assuming there are no `Object.prototype`
|
* enumerable properties and that there are no `Object.prototype` extensions.
|
||||||
* extensions.
|
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Mixed} value The value to check.
|
* @param {Mixed} value The value to check.
|
||||||
* @returns {Boolean} Returns `true` if `value` is an object, else `false`.
|
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, else `false`.
|
||||||
*/
|
*/
|
||||||
function isObject(value) {
|
function isPlainObject(value) {
|
||||||
var ctor,
|
// avoid non-objects and false positives for `arguments` objects in IE < 9
|
||||||
result = !!value && toString.call(value) == '[object Object]';
|
var result = false;
|
||||||
|
if (!(value && typeof value == 'object') || isArguments(value)) {
|
||||||
if (result && noArgumentsClass) {
|
return result;
|
||||||
// avoid false positives for `arguments` objects in IE < 9
|
|
||||||
result = !isArguments(value);
|
|
||||||
}
|
}
|
||||||
if (result) {
|
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
|
||||||
// IE < 9 presents nodes like `Object` objects:
|
// methods that are `typeof` "string" and still can coerce nodes to strings.
|
||||||
// IE < 8 are missing the node's constructor property
|
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
|
||||||
// IE 8 node constructors are typeof "object"
|
var ctor = value.constructor;
|
||||||
ctor = value.constructor;
|
if ((support.nodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
|
||||||
// check if the constructor is `Object` as `Object instanceof Object` is `true`
|
(!isClassOf(ctor, 'Function') || ctor instanceof ctor)) {
|
||||||
if ((result = isClassOf(ctor, 'Function') && ctor instanceof ctor)) {
|
// In most environments an object's own properties are iterated before
|
||||||
// An object's own properties are iterated before inherited properties.
|
// its inherited properties. If the last iterated property is an object's
|
||||||
// If the last iterated key belongs to an object's own property then
|
// own property then there are no inherited enumerable properties.
|
||||||
// there are no inherited enumerable properties.
|
if (support.iteratesOwnFirst) {
|
||||||
forProps(value, function(subValue, subKey) { result = subKey; });
|
forProps(value, function(subValue, subKey) {
|
||||||
result = result === true || hasKey(value, result);
|
result = subKey;
|
||||||
|
});
|
||||||
|
return result === false || hasKey(value, result);
|
||||||
}
|
}
|
||||||
|
// IE < 9 iterates inherited properties before own properties. If the first
|
||||||
|
// iterated property is an object's own property then there are no inherited
|
||||||
|
// enumerable properties.
|
||||||
|
forProps(value, function(subValue, subKey) {
|
||||||
|
result = !hasKey(value, subKey);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return result === false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1265,7 +1311,7 @@
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '[object Object]':
|
case '[object Object]':
|
||||||
isObject(value) && (clone = new ctor);
|
isPlainObject(value) && (clone = {});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[object Number]':
|
case '[object Number]':
|
||||||
@@ -2405,13 +2451,12 @@
|
|||||||
|
|
||||||
var source = {
|
var source = {
|
||||||
'setup': getSource(bench.setup, preprocess('m$.setup()')),
|
'setup': getSource(bench.setup, preprocess('m$.setup()')),
|
||||||
'fn': getSource(fn, preprocess('f$(' + fnArg + ')')),
|
'fn': getSource(fn, preprocess('m$.fn(' + fnArg + ')')),
|
||||||
'fnArg': fnArg,
|
'fnArg': fnArg,
|
||||||
'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
|
'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
|
||||||
};
|
};
|
||||||
|
|
||||||
var compiled = bench.compiled,
|
var count = bench.count = clone.count,
|
||||||
count = bench.count = clone.count,
|
|
||||||
decompilable = support.decompilation || stringable,
|
decompilable = support.decompilation || stringable,
|
||||||
id = bench.id,
|
id = bench.id,
|
||||||
isEmpty = !(source.fn || stringable),
|
isEmpty = !(source.fn || stringable),
|
||||||
@@ -2433,77 +2478,77 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compiled) {
|
// Compile in setup/teardown functions and the test loop.
|
||||||
// compile in setup/teardown functions and the test loop
|
// Create a new compiled test, instead of using the cached `bench.compiled`,
|
||||||
compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
|
// to avoid potential engine optimizations enabled over the life of the test.
|
||||||
preprocess(deferred
|
var compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
|
||||||
? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
|
preprocess(deferred
|
||||||
// when `deferred.cycles` is `0` then...
|
? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
|
||||||
'if(!d$.cycles){' +
|
// when `deferred.cycles` is `0` then...
|
||||||
// set `deferred.fn`
|
'if(!d$.cycles){' +
|
||||||
'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
|
// set `deferred.fn`
|
||||||
// set `deferred.teardown`
|
'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
|
||||||
'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
|
// set `deferred.teardown`
|
||||||
// execute the benchmark's `setup`
|
'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
|
||||||
'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
|
// execute the benchmark's `setup`
|
||||||
// start timer
|
'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
|
||||||
't$.start(d$);' +
|
// start timer
|
||||||
// execute `deferred.fn` and return a dummy object
|
't$.start(d$);' +
|
||||||
'}d$.fn();return{}'
|
// execute `deferred.fn` and return a dummy object
|
||||||
|
'}d$.fn();return{}'
|
||||||
|
|
||||||
: 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' +
|
: '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}"}'),
|
'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'),
|
||||||
|
source
|
||||||
|
));
|
||||||
|
|
||||||
|
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, timer) || {}).uid == 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 = createFunction(preprocess('t$'), interpolate(
|
||||||
|
preprocess(
|
||||||
|
(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$}'
|
||||||
|
),
|
||||||
source
|
source
|
||||||
));
|
));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isEmpty) {
|
// pretest one more time to check for errors
|
||||||
// Firefox may remove dead code from Function#toString results
|
bench.count = 1;
|
||||||
// http://bugzil.la/536085
|
compiled.call(bench, timer);
|
||||||
throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
|
bench.compiled = compiled;
|
||||||
}
|
|
||||||
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, timer) || {}).uid == uid && compiled;
|
|
||||||
bench.count = count;
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
compiled = null;
|
|
||||||
clone.error = e || new Error(String(e));
|
|
||||||
bench.count = count;
|
bench.count = count;
|
||||||
|
delete clone.error;
|
||||||
}
|
}
|
||||||
// fallback when a test exits early or errors during pretest
|
catch(e) {
|
||||||
if (decompilable && !compiled && !deferred && !isEmpty) {
|
bench.count = count;
|
||||||
compiled = createFunction(preprocess('t$'), interpolate(
|
if (clone.error) {
|
||||||
preprocess(
|
compiled = null;
|
||||||
(clone.error && !stringable
|
} else {
|
||||||
? '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$}'
|
|
||||||
),
|
|
||||||
source
|
|
||||||
));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// pretest one more time to check for errors
|
|
||||||
bench.count = 1;
|
|
||||||
compiled.call(bench, timer);
|
|
||||||
bench.compiled = compiled;
|
bench.compiled = compiled;
|
||||||
bench.count = count;
|
clone.error = e || new Error(String(e));
|
||||||
delete clone.error;
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
bench.count = count;
|
|
||||||
if (clone.error) {
|
|
||||||
compiled = null;
|
|
||||||
} else {
|
|
||||||
bench.compiled = compiled;
|
|
||||||
clone.error = e || new Error(String(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2698,20 +2743,18 @@
|
|||||||
sample = bench.stats.sample;
|
sample = bench.stats.sample;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a number of clones to the queue.
|
* Adds a clone to the queue.
|
||||||
*/
|
*/
|
||||||
function enqueue(count) {
|
function enqueue() {
|
||||||
while (count--) {
|
queue.push(bench.clone({
|
||||||
queue.push(bench.clone({
|
'_original': bench,
|
||||||
'_original': bench,
|
'events': {
|
||||||
'events': {
|
'abort': [update],
|
||||||
'abort': [update],
|
'cycle': [update],
|
||||||
'cycle': [update],
|
'error': [update],
|
||||||
'error': [update],
|
'start': [update]
|
||||||
'start': [update]
|
}
|
||||||
}
|
}));
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2817,14 +2860,14 @@
|
|||||||
}
|
}
|
||||||
// if time permits, increase sample size to reduce the margin of error
|
// if time permits, increase sample size to reduce the margin of error
|
||||||
if (queue.length < 2 && !maxedOut) {
|
if (queue.length < 2 && !maxedOut) {
|
||||||
enqueue(1);
|
enqueue();
|
||||||
}
|
}
|
||||||
// abort the invoke cycle when done
|
// abort the invoke cycle when done
|
||||||
event.aborted = done;
|
event.aborted = done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init queue and begin
|
// init queue and begin
|
||||||
enqueue(minSamples);
|
enqueue();
|
||||||
invoke(queue, {
|
invoke(queue, {
|
||||||
'name': 'run',
|
'name': 'run',
|
||||||
'args': { 'async': async },
|
'args': { 'async': async },
|
||||||
@@ -3048,6 +3091,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum time a benchmark is allowed to run before finishing (secs).
|
* The maximum time a benchmark is allowed to run before finishing (secs).
|
||||||
|
*
|
||||||
* Note: Cycle delays aren't counted toward the maximum time.
|
* Note: Cycle delays aren't counted toward the maximum time.
|
||||||
*
|
*
|
||||||
* @memberOf Benchmark.options
|
* @memberOf Benchmark.options
|
||||||
@@ -3221,7 +3265,7 @@
|
|||||||
* @memberOf Benchmark
|
* @memberOf Benchmark
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
'version': '1.0.0-pre',
|
'version': '1.0.0',
|
||||||
|
|
||||||
// an object of environment/feature detection flags
|
// an object of environment/feature detection flags
|
||||||
'support': support,
|
'support': support,
|
||||||
|
|||||||
17
vendor/docdown/README.md
vendored
17
vendor/docdown/README.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Docdown <sup>v1.0.0-pre</sup>
|
# Docdown <sup>v1.0.0</sup>
|
||||||
|
|
||||||
A simple JSDoc to Markdown documentation generator.
|
A simple JSDoc to Markdown documentation generator.
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ For a list of upcoming features, check out our [roadmap](https://github.com/jdal
|
|||||||
|
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
~~~ php
|
```php
|
||||||
require("docdown.php");
|
require("docdown.php");
|
||||||
|
|
||||||
// generate Markdown
|
// generate Markdown
|
||||||
@@ -20,18 +20,7 @@ $markdown = docdown(array(
|
|||||||
"path" => $filepath,
|
"path" => $filepath,
|
||||||
"url" => "https://github.com/username/project/blob/master/my.js"
|
"url" => "https://github.com/username/project/blob/master/my.js"
|
||||||
));
|
));
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Cloning this repo
|
|
||||||
|
|
||||||
To clone this repository just use:
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
git clone https://github.com/docdown/docdown.git
|
|
||||||
cd docdown
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Feel free to fork and send pull requests if you see improvements!
|
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|||||||
4
vendor/docdown/src/DocDown/Entry.php
vendored
4
vendor/docdown/src/DocDown/Entry.php
vendored
@@ -140,7 +140,7 @@ class Entry {
|
|||||||
preg_match('#\*\s*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
preg_match('#\*\s*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
if (count($result)) {
|
if (count($result)) {
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
||||||
$result = '~~~ ' . $this->lang . "\n" . $result . "\n~~~";
|
$result = '```' . $this->lang . "\n" . $result . "\n```";
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ class Entry {
|
|||||||
* @returns {Array} The entry `param` data.
|
* @returns {Array} The entry `param` data.
|
||||||
*/
|
*/
|
||||||
public function getParams( $index = null ) {
|
public function getParams( $index = null ) {
|
||||||
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[[^]]+\]|[$\w]+)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
|
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[.+\]|[$\w]+)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
|
||||||
if (count($result = array_filter(array_slice($result, 1)))) {
|
if (count($result = array_filter(array_slice($result, 1)))) {
|
||||||
// repurpose array
|
// repurpose array
|
||||||
foreach ($result as $param) {
|
foreach ($result as $param) {
|
||||||
|
|||||||
10
vendor/docdown/src/DocDown/Generator.php
vendored
10
vendor/docdown/src/DocDown/Generator.php
vendored
@@ -208,6 +208,7 @@ class Generator {
|
|||||||
$openTag = "\n<!-- div -->\n";
|
$openTag = "\n<!-- div -->\n";
|
||||||
$closeTag = "\n<!-- /div -->\n";
|
$closeTag = "\n<!-- /div -->\n";
|
||||||
$result = array('# ' . $this->options['title']);
|
$result = array('# ' . $this->options['title']);
|
||||||
|
$toc = 'toc';
|
||||||
|
|
||||||
// initialize $api array
|
// initialize $api array
|
||||||
foreach ($this->entries as $entry) {
|
foreach ($this->entries as $entry) {
|
||||||
@@ -304,10 +305,15 @@ class Generator {
|
|||||||
|
|
||||||
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
||||||
|
|
||||||
|
// assign TOC hash
|
||||||
|
if (count($result) == 2) {
|
||||||
|
$toc = $member;
|
||||||
|
}
|
||||||
|
|
||||||
// add root entry
|
// add root entry
|
||||||
array_push(
|
array_push(
|
||||||
$result,
|
$result,
|
||||||
$openTag, '## ' . (count($result) == 2 ? '<a id="toc"></a>' : '') . '`' . $member . '`',
|
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`',
|
||||||
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -401,7 +407,7 @@ class Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// close tags add TOC link reference
|
// close tags add TOC link reference
|
||||||
array_push($result, $closeTag, $closeTag, '', ' [1]: #toc "Jump back to the TOC."');
|
array_push($result, $closeTag, $closeTag, '', ' [1]: #' . $toc . ' "Jump back to the TOC."');
|
||||||
|
|
||||||
// cleanup whitespace
|
// cleanup whitespace
|
||||||
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
||||||
|
|||||||
20
vendor/platform.js/LICENSE.txt
vendored
Normal file
20
vendor/platform.js/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
98
vendor/platform.js/README.md
vendored
Normal file
98
vendor/platform.js/README.md
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
# 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 Adobe AIR 3.1, Chrome 5-21, Firefox 1.5-13, IE 6-9, Opera 9.25-12.01, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, 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
|
||||||
|
|
||||||
|
* [John-David Dalton](http://allyoucanleet.com/)
|
||||||
|
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
* [Mathias Bynens](http://mathiasbynens.be/)
|
||||||
|
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
||||||
996
vendor/platform.js/platform.js
vendored
Normal file
996
vendor/platform.js/platform.js
vendored
Normal file
@@ -0,0 +1,996 @@
|
|||||||
|
/*!
|
||||||
|
* Platform.js v1.0.0 <http://mths.be/platform>
|
||||||
|
* Copyright 2010-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
* Available under MIT license <http://mths.be/mit>
|
||||||
|
*/
|
||||||
|
;(function(window) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** 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 ? (window = global) : global);
|
||||||
|
|
||||||
|
/** Opera regexp */
|
||||||
|
var reOpera = /Opera/;
|
||||||
|
|
||||||
|
/** Used to resolve a value's internal [[Class]] */
|
||||||
|
var toString = {}.toString;
|
||||||
|
|
||||||
|
/** Detect Java environment */
|
||||||
|
var java = /Java/.test(getClassOf(window.java)) && window.java;
|
||||||
|
|
||||||
|
/** A character to represent alpha */
|
||||||
|
var alpha = java ? 'a' : '\u03b1';
|
||||||
|
|
||||||
|
/** A character to represent beta */
|
||||||
|
var beta = java ? 'b' : '\u03b2';
|
||||||
|
|
||||||
|
/** Browser document object */
|
||||||
|
var doc = window.document || {};
|
||||||
|
|
||||||
|
/** Used to check for own properties of an object */
|
||||||
|
var hasOwnProperty = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
/** Browser navigator object */
|
||||||
|
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 = window.operamini || window.opera;
|
||||||
|
|
||||||
|
/** Opera [[Class]] */
|
||||||
|
var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);
|
||||||
|
|
||||||
|
/** Possible global object */
|
||||||
|
var thisBinding = this;
|
||||||
|
|
||||||
|
/** Browser user agent string */
|
||||||
|
var userAgent = nav.userAgent || '';
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capitalizes a string value.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to capitalize.
|
||||||
|
* @returns {String} The capitalized string.
|
||||||
|
*/
|
||||||
|
function capitalize(string) {
|
||||||
|
string = String(string);
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iteration utility for arrays and objects.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array|Object} object The object to iterate over.
|
||||||
|
* @param {Function} callback The function called per iteration.
|
||||||
|
*/
|
||||||
|
function each(object, callback) {
|
||||||
|
var index = -1,
|
||||||
|
length = object.length;
|
||||||
|
|
||||||
|
if (length == length >>> 0) {
|
||||||
|
while (++index < length) {
|
||||||
|
callback(object[index], index, object);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
forOwn(object, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim and conditionally capitalize string values.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to format.
|
||||||
|
* @returns {String} The formatted string.
|
||||||
|
*/
|
||||||
|
function format(string) {
|
||||||
|
string = trim(string);
|
||||||
|
return /^(?:webOS|i(?:OS|P))/.test(string)
|
||||||
|
? string
|
||||||
|
: capitalize(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over an object's own properties, executing the `callback` for each.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} object The object to iterate over.
|
||||||
|
* @param {Function} callback The function executed per own property.
|
||||||
|
*/
|
||||||
|
function forOwn(object, callback) {
|
||||||
|
for (var key in object) {
|
||||||
|
hasKey(object, key) && callback(object[key], key, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal [[Class]] of a value.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Mixed} value The value.
|
||||||
|
* @returns {String} The [[Class]].
|
||||||
|
*/
|
||||||
|
function getClassOf(value) {
|
||||||
|
return value == null
|
||||||
|
? capitalize(value)
|
||||||
|
: toString.call(value).slice(8, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an object has the specified key as a direct property.
|
||||||
|
*
|
||||||
|
* @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`.
|
||||||
|
*/
|
||||||
|
function hasKey() {
|
||||||
|
// lazy define for others (not as accurate)
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
var parent = object != null && (object.constructor || Object).prototype;
|
||||||
|
return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
|
||||||
|
};
|
||||||
|
// for modern browsers
|
||||||
|
if (getClassOf(hasOwnProperty) == 'Function') {
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
return object != null && hasOwnProperty.call(object, key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// for Safari 2
|
||||||
|
else if ({}.__proto__ == Object.prototype) {
|
||||||
|
hasKey = function(object, key) {
|
||||||
|
var result = false;
|
||||||
|
if (object != null) {
|
||||||
|
object = Object(object);
|
||||||
|
object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return hasKey.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Host objects can return type values that are different from their actual
|
||||||
|
* data type. The objects we are concerned with usually return non-primitive
|
||||||
|
* types of object, function, or unknown.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @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';
|
||||||
|
return !/^(?:boolean|number|string|undefined)$/.test(type) &&
|
||||||
|
(type == 'object' ? !!object[property] : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a string for use in a RegExp constructor by making hyphens and
|
||||||
|
* spaces optional.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to qualify.
|
||||||
|
* @returns {String} The qualified string.
|
||||||
|
*/
|
||||||
|
function qualify(string) {
|
||||||
|
return String(string).replace(/([ -])(?!$)/g, '$1?');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bare-bones` Array#reduce` like utility function.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} array The array to iterate over.
|
||||||
|
* @param {Function} callback The function called per iteration.
|
||||||
|
* @param {Mixed} accumulator Initial value of the accumulator.
|
||||||
|
* @returns {Mixed} The accumulator.
|
||||||
|
*/
|
||||||
|
function reduce(array, callback) {
|
||||||
|
var accumulator = null;
|
||||||
|
each(array, function(value, index) {
|
||||||
|
accumulator = callback(accumulator, value, index, array);
|
||||||
|
});
|
||||||
|
return accumulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes leading and trailing whitespace from a string.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} string The string to trim.
|
||||||
|
* @returns {String} The trimmed string.
|
||||||
|
*/
|
||||||
|
function trim(string) {
|
||||||
|
return String(string).replace(/^ +| +$/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new platform object.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @param {String} [ua = navigator.userAgent] The user agent string.
|
||||||
|
* @returns {Object} A platform object.
|
||||||
|
*/
|
||||||
|
function parse(ua) {
|
||||||
|
|
||||||
|
ua || (ua = userAgent);
|
||||||
|
|
||||||
|
/** Temporary variable used over the script's lifetime */
|
||||||
|
var data;
|
||||||
|
|
||||||
|
/** The CPU architecture */
|
||||||
|
var arch = ua;
|
||||||
|
|
||||||
|
/** Platform description array */
|
||||||
|
var description = [];
|
||||||
|
|
||||||
|
/** Platform alpha/beta indicator */
|
||||||
|
var prerelease = null;
|
||||||
|
|
||||||
|
/** A flag to indicate that environment features should be used to resolve the platform */
|
||||||
|
var useFeatures = ua == userAgent;
|
||||||
|
|
||||||
|
/** The browser/environment version */
|
||||||
|
var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
|
||||||
|
|
||||||
|
/* Detectable layout engines (order is important) */
|
||||||
|
var layout = getLayout([
|
||||||
|
{ 'label': 'WebKit', 'pattern': 'AppleWebKit' },
|
||||||
|
'iCab',
|
||||||
|
'Presto',
|
||||||
|
'NetFront',
|
||||||
|
'Tasman',
|
||||||
|
'Trident',
|
||||||
|
'KHTML',
|
||||||
|
'Gecko'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Detectable browser names (order is important) */
|
||||||
|
var name = getName([
|
||||||
|
'Adobe AIR',
|
||||||
|
'Arora',
|
||||||
|
'Avant Browser',
|
||||||
|
'Camino',
|
||||||
|
'Epiphany',
|
||||||
|
'Fennec',
|
||||||
|
'Flock',
|
||||||
|
'Galeon',
|
||||||
|
'GreenBrowser',
|
||||||
|
'iCab',
|
||||||
|
'Iceweasel',
|
||||||
|
'Iron',
|
||||||
|
'K-Meleon',
|
||||||
|
'Konqueror',
|
||||||
|
'Lunascape',
|
||||||
|
'Maxthon',
|
||||||
|
'Midori',
|
||||||
|
'Nook Browser',
|
||||||
|
'PhantomJS',
|
||||||
|
'Raven',
|
||||||
|
'Rekonq',
|
||||||
|
'RockMelt',
|
||||||
|
'SeaMonkey',
|
||||||
|
{ 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
|
||||||
|
'Sleipnir',
|
||||||
|
'SlimBrowser',
|
||||||
|
'Sunrise',
|
||||||
|
'Swiftfox',
|
||||||
|
'WebPositive',
|
||||||
|
'Opera Mini',
|
||||||
|
'Opera',
|
||||||
|
'Chrome',
|
||||||
|
{ 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
|
||||||
|
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
|
||||||
|
{ 'label': 'IE', 'pattern': 'MSIE' },
|
||||||
|
'Safari'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Detectable products (order is important) */
|
||||||
|
var product = getProduct([
|
||||||
|
'BlackBerry',
|
||||||
|
{ 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
|
||||||
|
{ 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
|
||||||
|
'Google TV',
|
||||||
|
'iPad',
|
||||||
|
'iPod',
|
||||||
|
'iPhone',
|
||||||
|
'Kindle',
|
||||||
|
{ 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
|
||||||
|
'Nook',
|
||||||
|
'PlayBook',
|
||||||
|
'PlayStation Vita',
|
||||||
|
'TouchPad',
|
||||||
|
'Transformer',
|
||||||
|
'Xoom'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* Detectable manufacturers */
|
||||||
|
var manufacturer = getManufacturer({
|
||||||
|
'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
|
||||||
|
'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
|
||||||
|
'Asus': { 'Transformer': 1 },
|
||||||
|
'Barnes & Noble': { 'Nook': 1 },
|
||||||
|
'BlackBerry': { 'PlayBook': 1 },
|
||||||
|
'Google': { 'Google TV': 1 },
|
||||||
|
'HP': { 'TouchPad': 1 },
|
||||||
|
'LG': { },
|
||||||
|
'Motorola': { 'Xoom': 1 },
|
||||||
|
'Nokia': { },
|
||||||
|
'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 },
|
||||||
|
'Sony': { 'PlayStation Vita': 1 }
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Detectable OSes (order is important) */
|
||||||
|
var os = getOS([
|
||||||
|
'Android',
|
||||||
|
'CentOS',
|
||||||
|
'Debian',
|
||||||
|
'Fedora',
|
||||||
|
'FreeBSD',
|
||||||
|
'Gentoo',
|
||||||
|
'Haiku',
|
||||||
|
'Kubuntu',
|
||||||
|
'Linux Mint',
|
||||||
|
'Red Hat',
|
||||||
|
'SuSE',
|
||||||
|
'Ubuntu',
|
||||||
|
'Xubuntu',
|
||||||
|
'Cygwin',
|
||||||
|
'Symbian OS',
|
||||||
|
'hpwOS',
|
||||||
|
'webOS ',
|
||||||
|
'webOS',
|
||||||
|
'Tablet OS',
|
||||||
|
'Linux',
|
||||||
|
'Mac OS X',
|
||||||
|
'Macintosh',
|
||||||
|
'Mac',
|
||||||
|
'Windows 98;',
|
||||||
|
'Windows '
|
||||||
|
]);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the layout engine from an array of guesses.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected layout engine.
|
||||||
|
*/
|
||||||
|
function getLayout(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
return result || RegExp('\\b' + (
|
||||||
|
guess.pattern || qualify(guess)
|
||||||
|
) + '\\b', 'i').exec(ua) && (guess.label || guess);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the manufacturer from an array of guesses.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected manufacturer.
|
||||||
|
*/
|
||||||
|
function getManufacturer(guesses) {
|
||||||
|
return reduce(guesses, function(result, value, key) {
|
||||||
|
// lookup the manufacturer by product or scan the UA for the manufacturer
|
||||||
|
return result || (
|
||||||
|
value[product] ||
|
||||||
|
value[0/*Opera 9.25 fix*/, /^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
|
||||||
|
RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
|
||||||
|
) && (key.label || key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the browser name from an array of guesses.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected browser name.
|
||||||
|
*/
|
||||||
|
function getName(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
return result || RegExp('\\b' + (
|
||||||
|
guess.pattern || qualify(guess)
|
||||||
|
) + '\\b', 'i').exec(ua) && (guess.label || guess);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the OS name from an array of guesses.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected OS name.
|
||||||
|
*/
|
||||||
|
function getOS(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
var pattern = guess.pattern || qualify(guess);
|
||||||
|
if (!result && (result =
|
||||||
|
RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) {
|
||||||
|
// platform tokens defined at
|
||||||
|
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
||||||
|
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
|
||||||
|
data = {
|
||||||
|
'6.2': '8',
|
||||||
|
'6.1': 'Server 2008 R2 / 7',
|
||||||
|
'6.0': 'Server 2008 / Vista',
|
||||||
|
'5.2': 'Server 2003 / XP 64-bit',
|
||||||
|
'5.1': 'XP',
|
||||||
|
'5.01': '2000 SP1',
|
||||||
|
'5.0': '2000',
|
||||||
|
'4.0': 'NT',
|
||||||
|
'4.90': 'ME'
|
||||||
|
};
|
||||||
|
// detect Windows version from platform tokens
|
||||||
|
if (/^Win/i.test(result) &&
|
||||||
|
(data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) {
|
||||||
|
result = 'Windows ' + data;
|
||||||
|
}
|
||||||
|
// correct character case and cleanup
|
||||||
|
result = format(String(result)
|
||||||
|
.replace(RegExp(pattern, 'i'), guess.label || guess)
|
||||||
|
.replace(/ ce$/i, ' CE')
|
||||||
|
.replace(/hpw/i, 'web')
|
||||||
|
.replace(/Macintosh/, 'Mac OS')
|
||||||
|
.replace(/_PowerPC/i, ' OS')
|
||||||
|
.replace(/(OS X) [^ \d]+/i, '$1')
|
||||||
|
.replace(/\/(\d)/, ' $1')
|
||||||
|
.replace(/_/g, '.')
|
||||||
|
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
|
||||||
|
.replace(/x86\.64/gi, 'x86_64')
|
||||||
|
.split(' on ')[0]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks the product name from an array of guesses.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} guesses An array of guesses.
|
||||||
|
* @returns {String|Null} The detected product name.
|
||||||
|
*/
|
||||||
|
function getProduct(guesses) {
|
||||||
|
return reduce(guesses, function(result, guess) {
|
||||||
|
var pattern = guess.pattern || qualify(guess);
|
||||||
|
if (!result && (result =
|
||||||
|
RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
|
||||||
|
RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
|
||||||
|
)) {
|
||||||
|
// split by forward slash and append product version if needed
|
||||||
|
if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
|
||||||
|
result[0] += ' ' + result[1];
|
||||||
|
}
|
||||||
|
// correct character case and cleanup
|
||||||
|
guess = guess.label || guess;
|
||||||
|
result = format(result[0]
|
||||||
|
.replace(RegExp(pattern, 'i'), guess)
|
||||||
|
.replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
|
||||||
|
.replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2'));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the version using an array of UA patterns.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} patterns An array of UA patterns.
|
||||||
|
* @returns {String|Null} The detected version.
|
||||||
|
*/
|
||||||
|
function getVersion(patterns) {
|
||||||
|
return reduce(patterns, function(result, pattern) {
|
||||||
|
return result || (RegExp(pattern +
|
||||||
|
'(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `platform.description` when the platform object is coerced to a string.
|
||||||
|
*
|
||||||
|
* @name toString
|
||||||
|
* @memberOf platform
|
||||||
|
* @returns {String} Returns `platform.description` if available, else an empty string.
|
||||||
|
*/
|
||||||
|
function toStringPlatform() {
|
||||||
|
return this.description || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// convert layout to an array so we can add extra details
|
||||||
|
layout && (layout = [layout]);
|
||||||
|
|
||||||
|
// detect product names that contain their manufacturer's name
|
||||||
|
if (manufacturer && !product) {
|
||||||
|
product = getProduct([manufacturer]);
|
||||||
|
}
|
||||||
|
// clean up Google TV
|
||||||
|
if ((data = /Google TV/.exec(product))) {
|
||||||
|
product = data[0];
|
||||||
|
}
|
||||||
|
// detect simulators
|
||||||
|
if (/\bSimulator\b/i.test(ua)) {
|
||||||
|
product = (product ? product + ' ' : '') + 'Simulator';
|
||||||
|
}
|
||||||
|
// detect iOS
|
||||||
|
if (/^iP/.test(product)) {
|
||||||
|
name || (name = 'Safari');
|
||||||
|
os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
|
||||||
|
? ' ' + data[1].replace(/_/g, '.')
|
||||||
|
: '');
|
||||||
|
}
|
||||||
|
// detect Kubuntu
|
||||||
|
else if (name == 'Konqueror' && !/buntu/i.test(os)) {
|
||||||
|
os = 'Kubuntu';
|
||||||
|
}
|
||||||
|
// detect Android browsers
|
||||||
|
else if (manufacturer && manufacturer != 'Google' &&
|
||||||
|
/Chrome|Vita/.test(name + ';' + product)) {
|
||||||
|
name = 'Android Browser';
|
||||||
|
os = /Android/.test(os) ? os : 'Android';
|
||||||
|
}
|
||||||
|
// detect false positives for Firefox/Safari
|
||||||
|
else if (!name || (data = !/\bMinefield\b/i.test(ua) && /Firefox|Safari/.exec(name))) {
|
||||||
|
// escape the `/` for Firefox 1
|
||||||
|
if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
|
||||||
|
// clear name of false positives
|
||||||
|
name = null;
|
||||||
|
}
|
||||||
|
// reassign a generic name
|
||||||
|
if ((data = product || manufacturer || os) &&
|
||||||
|
(product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) {
|
||||||
|
name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect non-Opera versions (order is important)
|
||||||
|
if (!version) {
|
||||||
|
version = getVersion([
|
||||||
|
'(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
|
||||||
|
'Version',
|
||||||
|
qualify(name),
|
||||||
|
'(?:Firefox|Minefield|NetFront)'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
// detect stubborn layout engines
|
||||||
|
if (layout == 'iCab' && parseFloat(version) > 3) {
|
||||||
|
layout = ['WebKit'];
|
||||||
|
} else if (data =
|
||||||
|
/Opera/.test(name) && 'Presto' ||
|
||||||
|
/\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
|
||||||
|
!layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) {
|
||||||
|
layout = [data];
|
||||||
|
}
|
||||||
|
// leverage environment features
|
||||||
|
if (useFeatures) {
|
||||||
|
// detect server-side environments
|
||||||
|
// Rhino has a global function while others have a global object
|
||||||
|
if (isHostType(window, 'global')) {
|
||||||
|
if (java) {
|
||||||
|
data = java.lang.System;
|
||||||
|
arch = data.getProperty('os.arch');
|
||||||
|
os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
|
||||||
|
}
|
||||||
|
if (typeof exports == 'object' && exports) {
|
||||||
|
// if `thisBinding` is the [ModuleScope]
|
||||||
|
if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
|
||||||
|
os || (os = data[0].os || null);
|
||||||
|
try {
|
||||||
|
data[1] = require('ringo/engine').version;
|
||||||
|
version = data[1].join('.');
|
||||||
|
name = 'RingoJS';
|
||||||
|
} catch(e) {
|
||||||
|
if (data[0].global == freeGlobal) {
|
||||||
|
name = 'Narwhal';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof process == 'object' && (data = process)) {
|
||||||
|
name = 'Node.js';
|
||||||
|
arch = data.arch;
|
||||||
|
os = data.platform;
|
||||||
|
version = /[\d.]+/.exec(data.version)[0];
|
||||||
|
}
|
||||||
|
} else if (getClassOf(window.environment) == 'Environment') {
|
||||||
|
name = 'Rhino';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Adobe AIR
|
||||||
|
else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') {
|
||||||
|
name = 'Adobe AIR';
|
||||||
|
os = data.flash.system.Capabilities.os;
|
||||||
|
}
|
||||||
|
// detect PhantomJS
|
||||||
|
else if (getClassOf(data = window.phantom) == 'RuntimeObject') {
|
||||||
|
name = 'PhantomJS';
|
||||||
|
version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
|
||||||
|
}
|
||||||
|
// detect IE compatibility modes
|
||||||
|
else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
|
||||||
|
// we're in compatibility mode when the Trident version + 4 doesn't
|
||||||
|
// equal the document mode
|
||||||
|
version = [version, doc.documentMode];
|
||||||
|
if ((data = +data[1] + 4) != version[1]) {
|
||||||
|
description.push('IE ' + version[1] + ' mode');
|
||||||
|
layout[1] = '';
|
||||||
|
version[1] = data;
|
||||||
|
}
|
||||||
|
version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
|
||||||
|
}
|
||||||
|
os = os && format(os);
|
||||||
|
}
|
||||||
|
// detect prerelease phases
|
||||||
|
if (version && (data =
|
||||||
|
/(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
|
||||||
|
/(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
|
||||||
|
/\bMinefield\b/i.test(ua) && 'a')) {
|
||||||
|
prerelease = /b/i.test(data) ? 'beta' : 'alpha';
|
||||||
|
version = version.replace(RegExp(data + '\\+?$'), '') +
|
||||||
|
(prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
|
||||||
|
}
|
||||||
|
// rename code name "Fennec"
|
||||||
|
if (name == 'Fennec') {
|
||||||
|
name = 'Firefox Mobile';
|
||||||
|
}
|
||||||
|
// obscure Maxthon's unreliable version
|
||||||
|
else if (name == 'Maxthon' && version) {
|
||||||
|
version = version.replace(/\.[\d.]+/, '.x');
|
||||||
|
}
|
||||||
|
// detect Silk desktop/accelerated modes
|
||||||
|
else if (name == 'Silk') {
|
||||||
|
if (!/Mobi/i.test(ua)) {
|
||||||
|
os = 'Android';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
}
|
||||||
|
if (/Accelerated *= *true/i.test(ua)) {
|
||||||
|
description.unshift('accelerated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Windows Phone desktop mode
|
||||||
|
else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
|
||||||
|
name += ' Mobile';
|
||||||
|
os = 'Windows Phone OS ' + data + '.x';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
}
|
||||||
|
// add mobile postfix
|
||||||
|
else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&
|
||||||
|
(os == 'Windows CE' || /Mobi/i.test(ua))) {
|
||||||
|
name += ' Mobile';
|
||||||
|
}
|
||||||
|
// detect IE platform preview
|
||||||
|
else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) {
|
||||||
|
description.unshift('platform preview');
|
||||||
|
}
|
||||||
|
// detect BlackBerry OS version
|
||||||
|
// http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
|
||||||
|
else if (/BlackBerry/.test(product) && (data =
|
||||||
|
(RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
|
||||||
|
version)) {
|
||||||
|
os = 'Device Software ' + data;
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
// detect Opera identifying/masking itself as another browser
|
||||||
|
// http://www.opera.com/support/kb/view/843/
|
||||||
|
else if (this != forOwn && (
|
||||||
|
(useFeatures && opera) ||
|
||||||
|
(/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
|
||||||
|
(name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) ||
|
||||||
|
(name == 'IE' && (
|
||||||
|
(os && !/^Win/.test(os) && version > 5.5) ||
|
||||||
|
/Windows XP/.test(os) && version > 8 ||
|
||||||
|
version == 8 && !/Trident/.test(ua)
|
||||||
|
))
|
||||||
|
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
|
||||||
|
|
||||||
|
// when "indentifying", the UA contains both Opera and the other browser's name
|
||||||
|
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
|
||||||
|
if (reOpera.test(name)) {
|
||||||
|
if (/IE/.test(data) && os == 'Mac OS') {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
data = 'identify' + data;
|
||||||
|
}
|
||||||
|
// when "masking", the UA contains only the other browser's name
|
||||||
|
else {
|
||||||
|
data = 'mask' + data;
|
||||||
|
if (operaClass) {
|
||||||
|
name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
|
||||||
|
} else {
|
||||||
|
name = 'Opera';
|
||||||
|
}
|
||||||
|
if (/IE/.test(data)) {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
if (!useFeatures) {
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout = ['Presto'];
|
||||||
|
description.push(data);
|
||||||
|
}
|
||||||
|
// detect WebKit Nightly and approximate Chrome/Safari versions
|
||||||
|
if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
|
||||||
|
// correct build for numeric comparison
|
||||||
|
// (e.g. "532.5" becomes "532.05")
|
||||||
|
data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
|
||||||
|
// nightly builds are postfixed with a `+`
|
||||||
|
if (name == 'Safari' && data[1].slice(-1) == '+') {
|
||||||
|
name = 'WebKit Nightly';
|
||||||
|
prerelease = 'alpha';
|
||||||
|
version = data[1].slice(0, -1);
|
||||||
|
}
|
||||||
|
// clear incorrect browser versions
|
||||||
|
else if (version == data[1] ||
|
||||||
|
version == (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) {
|
||||||
|
version = null;
|
||||||
|
}
|
||||||
|
// use the full Chrome version when available
|
||||||
|
data = [data[0], (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]];
|
||||||
|
|
||||||
|
// detect JavaScriptCore
|
||||||
|
// http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
|
||||||
|
if (!useFeatures || (/internal|\n/i.test(toString.toString()) && !data[1])) {
|
||||||
|
layout[1] = 'like Safari';
|
||||||
|
data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
|
||||||
|
} else {
|
||||||
|
layout[1] = 'like Chrome';
|
||||||
|
data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : '21');
|
||||||
|
}
|
||||||
|
// add the postfix of ".x" or "+" for approximate versions
|
||||||
|
layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
|
||||||
|
// obscure version for some Safari 1-2 releases
|
||||||
|
if (name == 'Safari' && (!version || parseInt(version) > 45)) {
|
||||||
|
version = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Opera desktop modes
|
||||||
|
if (name == 'Opera' && (data = /(?:zbov|zvav)$/.exec(os))) {
|
||||||
|
name += ' ';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
if (data == 'zvav') {
|
||||||
|
name += 'Mini';
|
||||||
|
version = null;
|
||||||
|
} else {
|
||||||
|
name += 'Mobile';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Chrome desktop mode
|
||||||
|
else if (name == 'Safari' && /Chrome/.exec(layout[1])) {
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
name = 'Chrome Mobile';
|
||||||
|
version = null;
|
||||||
|
|
||||||
|
if (/Mac OS X/.test(os)) {
|
||||||
|
manufacturer = 'Apple';
|
||||||
|
os = 'iOS 4.3+';
|
||||||
|
} else {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// strip incorrect OS versions
|
||||||
|
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
|
||||||
|
ua.indexOf('/' + data + '-') > -1) {
|
||||||
|
os = trim(os.replace(data, ''));
|
||||||
|
}
|
||||||
|
// add layout engine
|
||||||
|
if (layout && !/Avant|Nook/.test(name) && (
|
||||||
|
/Browser|Lunascape|Maxthon/.test(name) ||
|
||||||
|
/^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) {
|
||||||
|
// don't add layout details to description if they are falsey
|
||||||
|
(data = layout[layout.length - 1]) && description.push(data);
|
||||||
|
}
|
||||||
|
// combine contextual information
|
||||||
|
if (description.length) {
|
||||||
|
description = ['(' + description.join('; ') + ')'];
|
||||||
|
}
|
||||||
|
// append manufacturer
|
||||||
|
if (manufacturer && product && product.indexOf(manufacturer) < 0) {
|
||||||
|
description.push('on ' + manufacturer);
|
||||||
|
}
|
||||||
|
// append product
|
||||||
|
if (product) {
|
||||||
|
description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
|
||||||
|
}
|
||||||
|
// parse OS into an object
|
||||||
|
if (os) {
|
||||||
|
data = / ([\d.+]+)$/.exec(os);
|
||||||
|
os = {
|
||||||
|
'architecture': 32,
|
||||||
|
'family': data ? os.replace(data[0], '') : os,
|
||||||
|
'version': data ? data[1] : null,
|
||||||
|
'toString': function() {
|
||||||
|
var version = this.version;
|
||||||
|
return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// add browser/OS architecture
|
||||||
|
if ((data = / (?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
|
||||||
|
if (os) {
|
||||||
|
os.architecture = 64;
|
||||||
|
os.family = os.family.replace(data, '');
|
||||||
|
}
|
||||||
|
if (name && (/WOW64/i.test(ua) ||
|
||||||
|
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
|
||||||
|
description.unshift('32-bit');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ua || (ua = null);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform object.
|
||||||
|
*
|
||||||
|
* @name platform
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
return {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The browser/environment version.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'version': name && version && (description.unshift(version), version),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the browser/environment.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'name': name && (description.unshift(name), name),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the operating system.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
'os': os
|
||||||
|
? (name &&
|
||||||
|
!(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product)) &&
|
||||||
|
description.push(product ? '(' + os + ')' : 'on ' + os), os)
|
||||||
|
: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CPU architecture the OS is built for.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'architecture': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The family of the OS.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'family': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of the OS.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'version': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OS string.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @returns {String} The OS string.
|
||||||
|
*/
|
||||||
|
'toString': function() { return 'null'; }
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform description.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'description': description.length ? description.join(' ') : ua,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the browser layout engine.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'layout': layout && layout[0],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the product's manufacturer.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'manufacturer': manufacturer,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The alpha/beta release indicator.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'prerelease': prerelease,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the product hosting the browser.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'product': product,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The browser's user agent string.
|
||||||
|
*
|
||||||
|
* @memberOf platform
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'ua': ua,
|
||||||
|
|
||||||
|
// parses a user agent string into a platform object
|
||||||
|
'parse': parse,
|
||||||
|
|
||||||
|
// returns the platform description
|
||||||
|
'toString': toStringPlatform
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// expose platform
|
||||||
|
// 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() {
|
||||||
|
return parse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// check for `exports` after `define` in case a build optimizer adds an `exports` object
|
||||||
|
else if (freeExports) {
|
||||||
|
// in Narwhal, Node.js, or RingoJS
|
||||||
|
forOwn(parse(), function(value, key) {
|
||||||
|
freeExports[key] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// in a browser or Rhino
|
||||||
|
else {
|
||||||
|
// use square bracket notation so Closure Compiler won't munge `platform`
|
||||||
|
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||||
|
window['platform'] = parse();
|
||||||
|
}
|
||||||
|
}(this));
|
||||||
28
vendor/qunit-clib/README.md
vendored
28
vendor/qunit-clib/README.md
vendored
@@ -1,15 +1,19 @@
|
|||||||
# QUnit CLIB <sup>v1.0.0-pre</sup>
|
# QUnit CLIB <sup>v1.0.0</sup>
|
||||||
## command-line interface boilerplate
|
## command-line interface boilerplate
|
||||||
|
|
||||||
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments<sup><a name="fnref1" href="#fn1">1</a></sup>.
|
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments.
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.6, Narwhal v0.3.2, RingoJS v0.8.0, and Rhino v1.7RC3-RC5.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
(function(window) {
|
(function(window) {
|
||||||
|
|
||||||
// use a single load function
|
// use a single load function
|
||||||
@@ -39,25 +43,13 @@ QUnit CLIB helps extend QUnit's CLI support to many common CLI environments<sup>
|
|||||||
QUnit.start();
|
QUnit.start();
|
||||||
}
|
}
|
||||||
}(typeof global == 'object' && global || this));
|
}(typeof global == 'object' && global || this));
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Cloning this repo
|
|
||||||
|
|
||||||
To clone this repository just use:
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
git clone https://github.com/jdalton/qunit-clib.git
|
|
||||||
cd qunit-clib
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Feel free to fork and send pull requests if you see improvements!
|
|
||||||
|
|
||||||
## Footnotes
|
## Footnotes
|
||||||
|
|
||||||
1. QUnit CLIB has been tested in at least Node.js v0.4.8-0.6.1, Narwhal v0.3.2, RingoJS v0.7.0-0.8.0, and Rhino v1.7RC3.
|
1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
|
||||||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
|
||||||
|
|
||||||
2. 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
|
## Author
|
||||||
|
|
||||||
|
|||||||
82
vendor/qunit-clib/qunit-clib.js
vendored
82
vendor/qunit-clib/qunit-clib.js
vendored
@@ -1,10 +1,11 @@
|
|||||||
/*!
|
/*!
|
||||||
* QUnit CLI Boilerplate v1.0.0-pre
|
* QUnit CLI Boilerplate v1.0.0
|
||||||
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
||||||
* Available under MIT license <http://mths.be/mit>
|
* Available under MIT license <http://mths.be/mit>
|
||||||
*/
|
*/
|
||||||
;(function(global) {
|
;(function(global) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
|
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
|
||||||
global.console || (global.console = { 'log': global.print });
|
global.console || (global.console = { 'log': global.print });
|
||||||
@@ -24,7 +25,8 @@
|
|||||||
var toString = {}.toString;
|
var toString = {}.toString;
|
||||||
|
|
||||||
/** Used by timer methods */
|
/** Used by timer methods */
|
||||||
var timer,
|
var doneCalled,
|
||||||
|
timer,
|
||||||
counter = 0,
|
counter = 0,
|
||||||
ids = {};
|
ids = {};
|
||||||
|
|
||||||
@@ -90,6 +92,8 @@
|
|||||||
* @returns {Number} The the ID of the timeout.
|
* @returns {Number} The the ID of the timeout.
|
||||||
*/
|
*/
|
||||||
function schedule(fn, delay, args, repeated) {
|
function schedule(fn, delay, args, repeated) {
|
||||||
|
// Rhino 1.7RC4 will error assigning `task` below
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=775566
|
||||||
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
||||||
'run': function() {
|
'run': function() {
|
||||||
fn.apply(global, args);
|
fn.apply(global, args);
|
||||||
@@ -149,26 +153,26 @@
|
|||||||
* `runtime`, and `total`.
|
* `runtime`, and `total`.
|
||||||
*/
|
*/
|
||||||
function done(details) {
|
function done(details) {
|
||||||
// stop `asyncTest()` from erroneously calling `done()` twice in environments w/o timeouts
|
// stop `asyncTest()` from erroneously calling `done()` twice in
|
||||||
if (!QUnit.doneCalled) {
|
// environments w/o timeouts
|
||||||
console.log(hr);
|
if (doneCalled) {
|
||||||
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
|
return;
|
||||||
console.log(' Finished in ' + details.runtime + ' milliseconds.');
|
|
||||||
console.log(hr);
|
|
||||||
|
|
||||||
// exit out of Rhino
|
|
||||||
try {
|
|
||||||
quit();
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
// exit out of Node.js
|
|
||||||
try {
|
|
||||||
process.exit();
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
// prevent multiple calls to `done()`
|
|
||||||
QUnit.doneCalled = true;
|
|
||||||
}
|
}
|
||||||
|
doneCalled = true;
|
||||||
|
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 Rhino
|
||||||
|
try {
|
||||||
|
quit();
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
// exit out of Node.js
|
||||||
|
try {
|
||||||
|
process.exit();
|
||||||
|
} catch(e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,12 +185,13 @@
|
|||||||
function log(details) {
|
function log(details) {
|
||||||
var expected = details.expected,
|
var expected = details.expected,
|
||||||
result = details.result,
|
result = details.result,
|
||||||
type = typeof expected != 'undefined' ? 'EQ' : 'OK',
|
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
|
||||||
assertion = [
|
|
||||||
result ? 'PASS' : 'FAIL',
|
var assertion = [
|
||||||
type,
|
result ? 'PASS' : 'FAIL',
|
||||||
details.message || 'ok'
|
type,
|
||||||
];
|
details.message || 'ok'
|
||||||
|
];
|
||||||
|
|
||||||
if (!result && type == 'EQ') {
|
if (!result && type == 'EQ') {
|
||||||
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
|
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
|
||||||
@@ -215,7 +220,7 @@
|
|||||||
* @returns {String} The result string.
|
* @returns {String} The result string.
|
||||||
*/
|
*/
|
||||||
var parseObject = (function() {
|
var parseObject = (function() {
|
||||||
var _parseObject = QUnit.jsDump.parsers.object;
|
var func = QUnit.jsDump.parsers.object;
|
||||||
return function(object) {
|
return function(object) {
|
||||||
// fork to support Rhino's error objects
|
// fork to support Rhino's error objects
|
||||||
if (typeof object.rhinoException == 'object') {
|
if (typeof object.rhinoException == 'object') {
|
||||||
@@ -224,7 +229,7 @@
|
|||||||
'", fileName: "' + object.fileName +
|
'", fileName: "' + object.fileName +
|
||||||
'", lineNumber: ' + object.lineNumber + ' }';
|
'", lineNumber: ' + object.lineNumber + ' }';
|
||||||
}
|
}
|
||||||
return _parseObject(object);
|
return func(object);
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|
||||||
@@ -237,16 +242,16 @@
|
|||||||
*/
|
*/
|
||||||
function testDone(details) {
|
function testDone(details) {
|
||||||
var assertions = QUnit.config.testStats.assertions,
|
var assertions = QUnit.config.testStats.assertions,
|
||||||
name = details.name;
|
testName = details.name;
|
||||||
|
|
||||||
if (details.failed > 0) {
|
if (details.failed > 0) {
|
||||||
console.log(' FAIL - '+ name);
|
console.log(' FAIL - '+ testName);
|
||||||
each(assertions, function(value) {
|
each(assertions, function(value) {
|
||||||
console.log(' ' + value);
|
console.log(' ' + value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(' PASS - ' + name);
|
console.log(' PASS - ' + testName);
|
||||||
}
|
}
|
||||||
assertions.length = 0;
|
assertions.length = 0;
|
||||||
}
|
}
|
||||||
@@ -274,8 +279,11 @@
|
|||||||
// exclude `module` because some environments have it as a built-in object
|
// exclude `module` because some environments have it as a built-in object
|
||||||
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
|
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
|
||||||
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
|
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
|
||||||
'strictEqual', 'test'], function(name) {
|
'strictEqual', 'test', 'throws'], function(funcName) {
|
||||||
global[name] = QUnit[name];
|
var func = QUnit[funcName];
|
||||||
|
if (func) {
|
||||||
|
global[funcName] = func;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// expose timer methods to global
|
// expose timer methods to global
|
||||||
@@ -301,11 +309,11 @@
|
|||||||
QUnit.moduleStart(moduleStart);
|
QUnit.moduleStart(moduleStart);
|
||||||
QUnit.testDone(testDone);
|
QUnit.testDone(testDone);
|
||||||
|
|
||||||
// wrap `parseObject`
|
// add wrapped function
|
||||||
QUnit.jsDump.parsers.object = parseObject;
|
QUnit.jsDump.parsers.object = parseObject;
|
||||||
|
|
||||||
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with Node.js
|
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
|
||||||
// or any version of QUnit with Narwhal, Rhino, or RingoJS
|
// Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
|
||||||
QUnit.init();
|
QUnit.init();
|
||||||
|
|
||||||
}(typeof global == 'object' && global || this));
|
}(typeof global == 'object' && global || this));
|
||||||
|
|||||||
9
vendor/qunit/README.md
vendored
9
vendor/qunit/README.md
vendored
@@ -41,8 +41,9 @@ Releases
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
Install git-extras and run `git changelog` to update History.md.
|
Install git-extras and run `git changelog` to update History.md.
|
||||||
Update qunit/qunit.js|css to the release version, commit and tag, update them
|
Update qunit/qunit.js|css and package.json to the release version, commit and
|
||||||
again to the next version, commit and push commits and tags.
|
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 (unlike the 1.1.0 release). Clean up the changelog,
|
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
|
||||||
removing merge commits or whitespace cleanups.
|
or whitespace cleanups.
|
||||||
|
|||||||
1863
vendor/qunit/qunit/qunit-1.8.0.js
vendored
Normal file
1863
vendor/qunit/qunit/qunit-1.8.0.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
vendor/qunit/qunit/qunit.css
vendored
41
vendor/qunit/qunit/qunit.css
vendored
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
|
||||||
*
|
*
|
||||||
* http://docs.jquery.com/QUnit
|
* http://docs.jquery.com/QUnit
|
||||||
*
|
*
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
|
||||||
border-radius: 15px 15px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
-moz-border-radius: 15px 15px 0 0;
|
-moz-border-radius: 5px 5px 0 0;
|
||||||
-webkit-border-top-right-radius: 15px;
|
-webkit-border-top-right-radius: 5px;
|
||||||
-webkit-border-top-left-radius: 15px;
|
-webkit-border-top-left-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-header a {
|
#qunit-header a {
|
||||||
@@ -54,9 +54,9 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-header label {
|
#qunit-testrunner-toolbar label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-left: 0.5em;
|
padding: 0 .5em 0 .1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-banner {
|
#qunit-banner {
|
||||||
@@ -113,13 +113,9 @@
|
|||||||
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
border-radius: 15px;
|
border-radius: 5px;
|
||||||
-moz-border-radius: 15px;
|
-moz-border-radius: 5px;
|
||||||
-webkit-border-radius: 15px;
|
-webkit-border-radius: 5px;
|
||||||
|
|
||||||
box-shadow: inset 0px 2px 13px #999;
|
|
||||||
-moz-box-shadow: inset 0px 2px 13px #999;
|
|
||||||
-webkit-box-shadow: inset 0px 2px 13px #999;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests table {
|
#qunit-tests table {
|
||||||
@@ -162,8 +158,7 @@
|
|||||||
#qunit-tests b.failed { color: #710909; }
|
#qunit-tests b.failed { color: #710909; }
|
||||||
|
|
||||||
#qunit-tests li li {
|
#qunit-tests li li {
|
||||||
margin: 0.5em;
|
padding: 5px;
|
||||||
padding: 0.4em 0.5em 0.4em 0.5em;
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
list-style-position: inside;
|
list-style-position: inside;
|
||||||
@@ -172,9 +167,9 @@
|
|||||||
/*** Passing Styles */
|
/*** Passing Styles */
|
||||||
|
|
||||||
#qunit-tests li li.pass {
|
#qunit-tests li li.pass {
|
||||||
color: #5E740B;
|
color: #3c510c;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-left: 26px solid #C6E746;
|
border-left: 10px solid #C6E746;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||||
@@ -190,15 +185,15 @@
|
|||||||
#qunit-tests li li.fail {
|
#qunit-tests li li.fail {
|
||||||
color: #710909;
|
color: #710909;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-left: 26px solid #EE5757;
|
border-left: 10px solid #EE5757;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests > li:last-child {
|
#qunit-tests > li:last-child {
|
||||||
border-radius: 0 0 15px 15px;
|
border-radius: 0 0 5px 5px;
|
||||||
-moz-border-radius: 0 0 15px 15px;
|
-moz-border-radius: 0 0 5px 5px;
|
||||||
-webkit-border-bottom-right-radius: 15px;
|
-webkit-border-bottom-right-radius: 5px;
|
||||||
-webkit-border-bottom-left-radius: 15px;
|
-webkit-border-bottom-left-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||||
|
|||||||
113
vendor/qunit/qunit/qunit.js
vendored
113
vendor/qunit/qunit/qunit.js
vendored
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
|
||||||
*
|
*
|
||||||
* http://docs.jquery.com/QUnit
|
* http://docs.jquery.com/QUnit
|
||||||
*
|
*
|
||||||
@@ -403,6 +403,8 @@ QUnit = {
|
|||||||
QUnit.assert = {
|
QUnit.assert = {
|
||||||
/**
|
/**
|
||||||
* Asserts rough true-ish result.
|
* Asserts rough true-ish result.
|
||||||
|
* @name ok
|
||||||
|
* @function
|
||||||
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
|
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
|
||||||
*/
|
*/
|
||||||
ok: function( result, msg ) {
|
ok: function( result, msg ) {
|
||||||
@@ -437,36 +439,59 @@ QUnit.assert = {
|
|||||||
/**
|
/**
|
||||||
* Assert that the first two arguments are equal, with an optional message.
|
* Assert that the first two arguments are equal, with an optional message.
|
||||||
* Prints out both actual and expected values.
|
* Prints out both actual and expected values.
|
||||||
|
* @name equal
|
||||||
|
* @function
|
||||||
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
|
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
|
||||||
*/
|
*/
|
||||||
equal: function( actual, expected, message ) {
|
equal: function( actual, expected, message ) {
|
||||||
QUnit.push( expected == actual, actual, expected, message );
|
QUnit.push( expected == actual, actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name notEqual
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
notEqual: function( actual, expected, message ) {
|
notEqual: function( actual, expected, message ) {
|
||||||
QUnit.push( expected != actual, actual, expected, message );
|
QUnit.push( expected != actual, actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name deepEqual
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
deepEqual: function( actual, expected, message ) {
|
deepEqual: function( actual, expected, message ) {
|
||||||
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
|
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name notDeepEqual
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
notDeepEqual: function( actual, expected, message ) {
|
notDeepEqual: function( actual, expected, message ) {
|
||||||
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
|
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name strictEqual
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
strictEqual: function( actual, expected, message ) {
|
strictEqual: function( actual, expected, message ) {
|
||||||
QUnit.push( expected === actual, actual, expected, message );
|
QUnit.push( expected === actual, actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name notStrictEqual
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
notStrictEqual: function( actual, expected, message ) {
|
notStrictEqual: function( actual, expected, message ) {
|
||||||
QUnit.push( expected !== actual, actual, expected, message );
|
QUnit.push( expected !== actual, actual, expected, message );
|
||||||
},
|
},
|
||||||
|
|
||||||
raises: function( block, expected, message ) {
|
throws: function( block, expected, message ) {
|
||||||
var actual,
|
var actual,
|
||||||
ok = false;
|
ok = false;
|
||||||
|
|
||||||
|
// 'expected' is optional
|
||||||
if ( typeof expected === "string" ) {
|
if ( typeof expected === "string" ) {
|
||||||
message = expected;
|
message = expected;
|
||||||
expected = null;
|
expected = null;
|
||||||
@@ -494,18 +519,29 @@ QUnit.assert = {
|
|||||||
} else if ( expected.call( {}, actual ) === true ) {
|
} else if ( expected.call( {}, actual ) === true ) {
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QUnit.push( ok, actual, null, message );
|
QUnit.push( ok, actual, null, message );
|
||||||
|
} else {
|
||||||
|
QUnit.pushFailure( message, null, 'No exception was thrown.' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// @deprecated: Kept assertion helpers in root for backwards compatibility
|
/**
|
||||||
|
* @deprecate since 1.8.0
|
||||||
|
* Kept assertion helpers in root for backwards compatibility
|
||||||
|
*/
|
||||||
extend( QUnit, QUnit.assert );
|
extend( QUnit, QUnit.assert );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated: Kept for backwards compatibility
|
* @deprecated since 1.9.0
|
||||||
* next step: remove entirely
|
* Kept global "raises()" for backwards compatibility
|
||||||
|
*/
|
||||||
|
QUnit.raises = QUnit.assert.throws;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
|
||||||
|
* Kept to avoid TypeErrors for undefined methods.
|
||||||
*/
|
*/
|
||||||
QUnit.equals = function() {
|
QUnit.equals = function() {
|
||||||
QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
|
QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
|
||||||
@@ -549,7 +585,20 @@ config = {
|
|||||||
// when enabled, all tests must call expect()
|
// when enabled, all tests must call expect()
|
||||||
requireExpects: false,
|
requireExpects: false,
|
||||||
|
|
||||||
urlConfig: [ "noglobals", "notrycatch" ],
|
// add checkboxes that are persisted in the query-string
|
||||||
|
// when enabled, the id is set to `true` as a `QUnit.config` property
|
||||||
|
urlConfig: [
|
||||||
|
{
|
||||||
|
id: "noglobals",
|
||||||
|
label: "Check for Globals",
|
||||||
|
tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "notrycatch",
|
||||||
|
label: "No try-catch",
|
||||||
|
tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
// logging callback queues
|
// logging callback queues
|
||||||
begin: [],
|
begin: [],
|
||||||
@@ -770,7 +819,7 @@ extend( QUnit, {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
pushFailure: function( message, source ) {
|
pushFailure: function( message, source, actual ) {
|
||||||
if ( !config.current ) {
|
if ( !config.current ) {
|
||||||
throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
|
throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
|
||||||
}
|
}
|
||||||
@@ -781,15 +830,23 @@ extend( QUnit, {
|
|||||||
message: message
|
message: message
|
||||||
};
|
};
|
||||||
|
|
||||||
message = escapeInnerText(message ) || "error";
|
message = escapeInnerText( message ) || "error";
|
||||||
message = "<span class='test-message'>" + message + "</span>";
|
message = "<span class='test-message'>" + message + "</span>";
|
||||||
output = message;
|
output = message;
|
||||||
|
|
||||||
|
output += "<table>";
|
||||||
|
|
||||||
|
if ( actual ) {
|
||||||
|
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>";
|
||||||
|
}
|
||||||
|
|
||||||
if ( source ) {
|
if ( source ) {
|
||||||
details.source = source;
|
details.source = source;
|
||||||
output += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>";
|
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output += "</table>";
|
||||||
|
|
||||||
runLoggingCallbacks( "log", QUnit, details );
|
runLoggingCallbacks( "log", QUnit, details );
|
||||||
|
|
||||||
config.current.assertions.push({
|
config.current.assertions.push({
|
||||||
@@ -859,7 +916,7 @@ QUnit.load = function() {
|
|||||||
runLoggingCallbacks( "begin", QUnit, {} );
|
runLoggingCallbacks( "begin", QUnit, {} );
|
||||||
|
|
||||||
// Initialize the config, saving the execution queue
|
// Initialize the config, saving the execution queue
|
||||||
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
|
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
|
||||||
urlConfigHtml = "",
|
urlConfigHtml = "",
|
||||||
oldconfig = extend( {}, config );
|
oldconfig = extend( {}, config );
|
||||||
|
|
||||||
@@ -872,8 +929,15 @@ QUnit.load = function() {
|
|||||||
|
|
||||||
for ( i = 0; i < len; i++ ) {
|
for ( i = 0; i < len; i++ ) {
|
||||||
val = config.urlConfig[i];
|
val = config.urlConfig[i];
|
||||||
config[val] = QUnit.urlParams[val];
|
if ( typeof val === "string" ) {
|
||||||
urlConfigHtml += "<label><input name='" + val + "' type='checkbox'" + ( config[val] ? " checked='checked'" : "" ) + ">" + val + "</label>";
|
val = {
|
||||||
|
id: val,
|
||||||
|
label: val,
|
||||||
|
tooltip: "[no tooltip available]"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
config[ val.id ] = QUnit.urlParams[ val.id ];
|
||||||
|
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
|
||||||
}
|
}
|
||||||
|
|
||||||
// `userAgent` initialized at top of scope
|
// `userAgent` initialized at top of scope
|
||||||
@@ -885,12 +949,7 @@ QUnit.load = function() {
|
|||||||
// `banner` initialized at top of scope
|
// `banner` initialized at top of scope
|
||||||
banner = id( "qunit-header" );
|
banner = id( "qunit-header" );
|
||||||
if ( banner ) {
|
if ( banner ) {
|
||||||
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined }) + "'>" + banner.innerHTML + "</a> " + urlConfigHtml;
|
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
|
||||||
addEvent( banner, "change", function( event ) {
|
|
||||||
var params = {};
|
|
||||||
params[ event.target.name ] = event.target.checked ? true : undefined;
|
|
||||||
window.location = QUnit.url( params );
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `toolbar` initialized at top of scope
|
// `toolbar` initialized at top of scope
|
||||||
@@ -931,8 +990,18 @@ QUnit.load = function() {
|
|||||||
// `label` initialized at top of scope
|
// `label` initialized at top of scope
|
||||||
label = document.createElement( "label" );
|
label = document.createElement( "label" );
|
||||||
label.setAttribute( "for", "qunit-filter-pass" );
|
label.setAttribute( "for", "qunit-filter-pass" );
|
||||||
|
label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
|
||||||
label.innerHTML = "Hide passed tests";
|
label.innerHTML = "Hide passed tests";
|
||||||
toolbar.appendChild( label );
|
toolbar.appendChild( label );
|
||||||
|
|
||||||
|
urlConfigCheckboxes = document.createElement( 'span' );
|
||||||
|
urlConfigCheckboxes.innerHTML = urlConfigHtml;
|
||||||
|
addEvent( urlConfigCheckboxes, "change", function( event ) {
|
||||||
|
var params = {};
|
||||||
|
params[ event.target.name ] = event.target.checked ? true : undefined;
|
||||||
|
window.location = QUnit.url( params );
|
||||||
|
});
|
||||||
|
toolbar.appendChild( urlConfigCheckboxes );
|
||||||
}
|
}
|
||||||
|
|
||||||
// `main` initialized at top of scope
|
// `main` initialized at top of scope
|
||||||
@@ -1051,14 +1120,14 @@ function done() {
|
|||||||
function validTest( test ) {
|
function validTest( test ) {
|
||||||
var include,
|
var include,
|
||||||
filter = config.filter && config.filter.toLowerCase(),
|
filter = config.filter && config.filter.toLowerCase(),
|
||||||
module = config.module,
|
module = config.module && config.module.toLowerCase(),
|
||||||
fullName = (test.module + ": " + test.testName).toLowerCase();
|
fullName = (test.module + ": " + test.testName).toLowerCase();
|
||||||
|
|
||||||
if ( config.testNumber ) {
|
if ( config.testNumber ) {
|
||||||
return test.testNumber === config.testNumber;
|
return test.testNumber === config.testNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( module && test.module !== module ) {
|
if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
227
vendor/requirejs/require.js
vendored
227
vendor/requirejs/require.js
vendored
@@ -1,21 +1,25 @@
|
|||||||
/** vim: et:ts=4:sw=4:sts=4
|
/** vim: et:ts=4:sw=4:sts=4
|
||||||
* @license RequireJS 2.0.4 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
* @license RequireJS 2.0.6 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||||
* Available via the MIT or new BSD license.
|
* Available via the MIT or new BSD license.
|
||||||
* see: http://github.com/jrburke/requirejs for details
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*jslint regexp: true, nomen: true */
|
//Not using strict: uneven strict support in browsers, #392, and causes
|
||||||
|
//problems with requirejs.exec()/transpiler plugins that may not be strict.
|
||||||
|
/*jslint regexp: true, nomen: true, sloppy: true */
|
||||||
/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
|
/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
|
||||||
|
|
||||||
var requirejs, require, define;
|
var requirejs, require, define;
|
||||||
(function (global) {
|
(function (global) {
|
||||||
'use strict';
|
var req, s, head, baseElement, dataMain, src,
|
||||||
|
interactiveScript, currentlyAddingScript, mainScript, subPath,
|
||||||
var version = '2.0.4',
|
version = '2.0.6',
|
||||||
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
|
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
|
||||||
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
||||||
jsSuffixRegExp = /\.js$/,
|
jsSuffixRegExp = /\.js$/,
|
||||||
currDirRegExp = /^\.\//,
|
currDirRegExp = /^\.\//,
|
||||||
ostring = Object.prototype.toString,
|
op = Object.prototype,
|
||||||
|
ostring = op.toString,
|
||||||
|
hasOwn = op.hasOwnProperty,
|
||||||
ap = Array.prototype,
|
ap = Array.prototype,
|
||||||
aps = ap.slice,
|
aps = ap.slice,
|
||||||
apsp = ap.splice,
|
apsp = ap.splice,
|
||||||
@@ -33,9 +37,7 @@ var requirejs, require, define;
|
|||||||
contexts = {},
|
contexts = {},
|
||||||
cfg = {},
|
cfg = {},
|
||||||
globalDefQueue = [],
|
globalDefQueue = [],
|
||||||
useInteractive = false,
|
useInteractive = false;
|
||||||
req, s, head, baseElement, dataMain, src,
|
|
||||||
interactiveScript, currentlyAddingScript, mainScript, subPath;
|
|
||||||
|
|
||||||
function isFunction(it) {
|
function isFunction(it) {
|
||||||
return ostring.call(it) === '[object Function]';
|
return ostring.call(it) === '[object Function]';
|
||||||
@@ -76,7 +78,7 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hasProp(obj, prop) {
|
function hasProp(obj, prop) {
|
||||||
return obj.hasOwnProperty(prop);
|
return hasOwn.call(obj, prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,7 +154,7 @@ var requirejs, require, define;
|
|||||||
//look up paths relative to the moduleName
|
//look up paths relative to the moduleName
|
||||||
var args = aps.call(arguments, 0), lastArg;
|
var args = aps.call(arguments, 0), lastArg;
|
||||||
if (enableBuildCallback &&
|
if (enableBuildCallback &&
|
||||||
isFunction((lastArg = args[args.length - 1]))) {
|
isFunction((lastArg = args[args.length - 1]))) {
|
||||||
lastArg.__requireJsBuild = true;
|
lastArg.__requireJsBuild = true;
|
||||||
}
|
}
|
||||||
args.push(relMap);
|
args.push(relMap);
|
||||||
@@ -169,14 +171,14 @@ var requirejs, require, define;
|
|||||||
], function (item) {
|
], function (item) {
|
||||||
var prop = item[1] || item[0];
|
var prop = item[1] || item[0];
|
||||||
req[item[0]] = context ? makeContextModuleFunc(context[prop], relMap) :
|
req[item[0]] = context ? makeContextModuleFunc(context[prop], relMap) :
|
||||||
//If no context, then use default context. Reference from
|
//If no context, then use default context. Reference from
|
||||||
//contexts instead of early binding to default context, so
|
//contexts instead of early binding to default context, so
|
||||||
//that during builds, the latest instance of the default
|
//that during builds, the latest instance of the default
|
||||||
//context with its config gets used.
|
//context with its config gets used.
|
||||||
function () {
|
function () {
|
||||||
var ctx = contexts[defContextName];
|
var ctx = contexts[defContextName];
|
||||||
return ctx[prop].apply(ctx, arguments);
|
return ctx[prop].apply(ctx, arguments);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +223,9 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function newContext(contextName) {
|
function newContext(contextName) {
|
||||||
var config = {
|
var inCheckLoaded, Module, context, handlers,
|
||||||
|
checkLoadedTimeoutId,
|
||||||
|
config = {
|
||||||
waitSeconds: 7,
|
waitSeconds: 7,
|
||||||
baseUrl: './',
|
baseUrl: './',
|
||||||
paths: {},
|
paths: {},
|
||||||
@@ -239,9 +243,7 @@ var requirejs, require, define;
|
|||||||
//should be executed, by the order they
|
//should be executed, by the order they
|
||||||
//load. Important for consistent cycle resolution
|
//load. Important for consistent cycle resolution
|
||||||
//behavior.
|
//behavior.
|
||||||
waitAry = [],
|
waitAry = [];
|
||||||
inCheckLoaded, Module, context, handlers,
|
|
||||||
checkLoadedTimeoutId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trims the . and .. from an array of path segments.
|
* Trims the . and .. from an array of path segments.
|
||||||
@@ -254,7 +256,7 @@ var requirejs, require, define;
|
|||||||
*/
|
*/
|
||||||
function trimDots(ary) {
|
function trimDots(ary) {
|
||||||
var i, part;
|
var i, part;
|
||||||
for (i = 0; ary[i]; i+= 1) {
|
for (i = 0; ary[i]; i += 1) {
|
||||||
part = ary[i];
|
part = ary[i];
|
||||||
if (part === '.') {
|
if (part === '.') {
|
||||||
ary.splice(i, 1);
|
ary.splice(i, 1);
|
||||||
@@ -287,12 +289,12 @@ var requirejs, require, define;
|
|||||||
* @returns {String} normalized name
|
* @returns {String} normalized name
|
||||||
*/
|
*/
|
||||||
function normalize(name, baseName, applyMap) {
|
function normalize(name, baseName, applyMap) {
|
||||||
var baseParts = baseName && baseName.split('/'),
|
var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
|
||||||
|
foundMap, foundI, foundStarMap, starI,
|
||||||
|
baseParts = baseName && baseName.split('/'),
|
||||||
normalizedBaseParts = baseParts,
|
normalizedBaseParts = baseParts,
|
||||||
map = config.map,
|
map = config.map,
|
||||||
starMap = map && map['*'],
|
starMap = map && map['*'];
|
||||||
pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,
|
|
||||||
foundMap;
|
|
||||||
|
|
||||||
//Adjust any relative paths.
|
//Adjust any relative paths.
|
||||||
if (name && name.charAt(0) === '.') {
|
if (name && name.charAt(0) === '.') {
|
||||||
@@ -343,28 +345,41 @@ var requirejs, require, define;
|
|||||||
for (j = baseParts.length; j > 0; j -= 1) {
|
for (j = baseParts.length; j > 0; j -= 1) {
|
||||||
mapValue = map[baseParts.slice(0, j).join('/')];
|
mapValue = map[baseParts.slice(0, j).join('/')];
|
||||||
|
|
||||||
//baseName segment has config, find if it has one for
|
//baseName segment has config, find if it has one for
|
||||||
//this name.
|
//this name.
|
||||||
if (mapValue) {
|
if (mapValue) {
|
||||||
mapValue = mapValue[nameSegment];
|
mapValue = mapValue[nameSegment];
|
||||||
if (mapValue) {
|
if (mapValue) {
|
||||||
//Match, update name to the new value.
|
//Match, update name to the new value.
|
||||||
foundMap = mapValue;
|
foundMap = mapValue;
|
||||||
|
foundI = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundMap && starMap && starMap[nameSegment]) {
|
|
||||||
foundMap = starMap[nameSegment];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundMap) {
|
if (foundMap) {
|
||||||
nameParts.splice(0, i, foundMap);
|
|
||||||
name = nameParts.join('/');
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check for a star map match, but just hold on to it,
|
||||||
|
//if there is a shorter segment match later in a matching
|
||||||
|
//config, then favor over this star map.
|
||||||
|
if (!foundStarMap && starMap && starMap[nameSegment]) {
|
||||||
|
foundStarMap = starMap[nameSegment];
|
||||||
|
starI = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundMap && foundStarMap) {
|
||||||
|
foundMap = foundStarMap;
|
||||||
|
foundI = starI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundMap) {
|
||||||
|
nameParts.splice(0, foundI, foundMap);
|
||||||
|
name = nameParts.join('/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +390,7 @@ var requirejs, require, define;
|
|||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
each(scripts(), function (scriptNode) {
|
each(scripts(), function (scriptNode) {
|
||||||
if (scriptNode.getAttribute('data-requiremodule') === name &&
|
if (scriptNode.getAttribute('data-requiremodule') === name &&
|
||||||
scriptNode.getAttribute('data-requirecontext') === context.contextName) {
|
scriptNode.getAttribute('data-requirecontext') === context.contextName) {
|
||||||
scriptNode.parentNode.removeChild(scriptNode);
|
scriptNode.parentNode.removeChild(scriptNode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -412,13 +427,13 @@ var requirejs, require, define;
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
|
function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
|
||||||
var index = name ? name.indexOf('!') : -1,
|
var url, pluginModule, suffix,
|
||||||
|
index = name ? name.indexOf('!') : -1,
|
||||||
prefix = null,
|
prefix = null,
|
||||||
parentName = parentModuleMap ? parentModuleMap.name : null,
|
parentName = parentModuleMap ? parentModuleMap.name : null,
|
||||||
originalName = name,
|
originalName = name,
|
||||||
isDefine = true,
|
isDefine = true,
|
||||||
normalizedName = '',
|
normalizedName = '';
|
||||||
url, pluginModule, suffix;
|
|
||||||
|
|
||||||
//If no name, then it means it is a require call, generate an
|
//If no name, then it means it is a require call, generate an
|
||||||
//internal name.
|
//internal name.
|
||||||
@@ -471,8 +486,8 @@ var requirejs, require, define;
|
|||||||
originalName: originalName,
|
originalName: originalName,
|
||||||
isDefine: isDefine,
|
isDefine: isDefine,
|
||||||
id: (prefix ?
|
id: (prefix ?
|
||||||
prefix + '!' + normalizedName :
|
prefix + '!' + normalizedName :
|
||||||
normalizedName) + suffix
|
normalizedName) + suffix
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +507,7 @@ var requirejs, require, define;
|
|||||||
mod = registry[id];
|
mod = registry[id];
|
||||||
|
|
||||||
if (hasProp(defined, id) &&
|
if (hasProp(defined, id) &&
|
||||||
(!mod || mod.defineEmitComplete)) {
|
(!mod || mod.defineEmitComplete)) {
|
||||||
if (name === 'defined') {
|
if (name === 'defined') {
|
||||||
fn(defined[id]);
|
fn(defined[id]);
|
||||||
}
|
}
|
||||||
@@ -597,7 +612,7 @@ var requirejs, require, define;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function findCycle(mod, traced) {
|
function findCycle(mod, traced, processed) {
|
||||||
var id = mod.map.id,
|
var id = mod.map.id,
|
||||||
depArray = mod.depMaps,
|
depArray = mod.depMaps,
|
||||||
foundModule;
|
foundModule;
|
||||||
@@ -620,28 +635,16 @@ var requirejs, require, define;
|
|||||||
var depId = depMap.id,
|
var depId = depMap.id,
|
||||||
depMod = registry[depId];
|
depMod = registry[depId];
|
||||||
|
|
||||||
if (!depMod) {
|
if (!depMod || processed[depId] ||
|
||||||
|
!depMod.inited || !depMod.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!depMod.inited || !depMod.enabled) {
|
return (foundModule = findCycle(depMod, traced, processed));
|
||||||
//Dependency is not inited, so this cannot
|
|
||||||
//be used to determine a cycle.
|
|
||||||
foundModule = null;
|
|
||||||
delete traced[id];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//mixin traced to a new object for each dependency, so that
|
|
||||||
//sibling dependencies in this object to not generate a
|
|
||||||
//false positive match on a cycle. Ideally an Object.create
|
|
||||||
//type of prototype delegation would be used here, but
|
|
||||||
//optimizing for file size vs. execution speed since hopefully
|
|
||||||
//the trees are small for circular dependency scans relative
|
|
||||||
//to the full app perf.
|
|
||||||
return (foundModule = findCycle(depMod, mixin({}, traced)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
processed[id] = true;
|
||||||
|
|
||||||
return foundModule;
|
return foundModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,7 +662,7 @@ var requirejs, require, define;
|
|||||||
|
|
||||||
traced[id] = mod;
|
traced[id] = mod;
|
||||||
|
|
||||||
each(depArray, function(depMap) {
|
each(depArray, function (depMap) {
|
||||||
var depId = depMap.id,
|
var depId = depMap.id,
|
||||||
depMod = registry[depId],
|
depMod = registry[depId],
|
||||||
value;
|
value;
|
||||||
@@ -699,13 +702,13 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkLoaded() {
|
function checkLoaded() {
|
||||||
var waitInterval = config.waitSeconds * 1000,
|
var map, modId, err, usingPathFallback,
|
||||||
|
waitInterval = config.waitSeconds * 1000,
|
||||||
//It is possible to disable the wait interval by using waitSeconds of 0.
|
//It is possible to disable the wait interval by using waitSeconds of 0.
|
||||||
expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
|
expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
|
||||||
noLoads = [],
|
noLoads = [],
|
||||||
stillLoading = false,
|
stillLoading = false,
|
||||||
needCycleCheck = true,
|
needCycleCheck = true;
|
||||||
map, modId, err, usingPathFallback;
|
|
||||||
|
|
||||||
//Do not bother if this call was a result of a cycle break.
|
//Do not bother if this call was a result of a cycle break.
|
||||||
if (inCheckLoaded) {
|
if (inCheckLoaded) {
|
||||||
@@ -764,7 +767,7 @@ var requirejs, require, define;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cycleMod = findCycle(mod, {}),
|
var cycleMod = findCycle(mod, {}, {}),
|
||||||
traced = {};
|
traced = {};
|
||||||
|
|
||||||
if (cycleMod) {
|
if (cycleMod) {
|
||||||
@@ -819,7 +822,7 @@ var requirejs, require, define;
|
|||||||
};
|
};
|
||||||
|
|
||||||
Module.prototype = {
|
Module.prototype = {
|
||||||
init: function(depMaps, factory, errback, options) {
|
init: function (depMaps, factory, errback, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
//Do not do more inits if already done. Can happen if there
|
//Do not do more inits if already done. Can happen if there
|
||||||
@@ -916,7 +919,7 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
load: function() {
|
load: function () {
|
||||||
var url = this.map.url;
|
var url = this.map.url;
|
||||||
|
|
||||||
//Regular dependency.
|
//Regular dependency.
|
||||||
@@ -937,11 +940,11 @@ var requirejs, require, define;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = this.map.id,
|
var err, cjsModule,
|
||||||
|
id = this.map.id,
|
||||||
depExports = this.depExports,
|
depExports = this.depExports,
|
||||||
exports = this.exports,
|
exports = this.exports,
|
||||||
factory = this.factory,
|
factory = this.factory;
|
||||||
err, cjsModule;
|
|
||||||
|
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
this.fetch();
|
this.fetch();
|
||||||
@@ -974,9 +977,9 @@ var requirejs, require, define;
|
|||||||
//favor a non-undefined return value over exports use.
|
//favor a non-undefined return value over exports use.
|
||||||
cjsModule = this.module;
|
cjsModule = this.module;
|
||||||
if (cjsModule &&
|
if (cjsModule &&
|
||||||
cjsModule.exports !== undefined &&
|
cjsModule.exports !== undefined &&
|
||||||
//Make sure it is not already the exports value
|
//Make sure it is not already the exports value
|
||||||
cjsModule.exports !== this.exports) {
|
cjsModule.exports !== this.exports) {
|
||||||
exports = cjsModule.exports;
|
exports = cjsModule.exports;
|
||||||
} else if (exports === undefined && this.usingExports) {
|
} else if (exports === undefined && this.usingExports) {
|
||||||
//exports already set the defined value.
|
//exports already set the defined value.
|
||||||
@@ -1032,15 +1035,15 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
callPlugin: function() {
|
callPlugin: function () {
|
||||||
var map = this.map,
|
var map = this.map,
|
||||||
id = map.id,
|
id = map.id,
|
||||||
pluginMap = makeModuleMap(map.prefix, null, false, true);
|
pluginMap = makeModuleMap(map.prefix, null, false, true);
|
||||||
|
|
||||||
on(pluginMap, 'defined', bind(this, function (plugin) {
|
on(pluginMap, 'defined', bind(this, function (plugin) {
|
||||||
var name = this.map.name,
|
var load, normalizedMap, normalizedMod,
|
||||||
parentName = this.map.parentMap ? this.map.parentMap.name : null,
|
name = this.map.name,
|
||||||
load, normalizedMap, normalizedMod;
|
parentName = this.map.parentMap ? this.map.parentMap.name : null;
|
||||||
|
|
||||||
//If current map is not normalized, wait for that
|
//If current map is not normalized, wait for that
|
||||||
//normalized name to load instead of continuing.
|
//normalized name to load instead of continuing.
|
||||||
@@ -1057,12 +1060,12 @@ var requirejs, require, define;
|
|||||||
false,
|
false,
|
||||||
true);
|
true);
|
||||||
on(normalizedMap,
|
on(normalizedMap,
|
||||||
'defined', bind(this, function (value) {
|
'defined', bind(this, function (value) {
|
||||||
this.init([], function () { return value; }, null, {
|
this.init([], function () { return value; }, null, {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ignore: true
|
ignore: true
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
normalizedMod = registry[normalizedMap.id];
|
normalizedMod = registry[normalizedMap.id];
|
||||||
if (normalizedMod) {
|
if (normalizedMod) {
|
||||||
if (this.events.error) {
|
if (this.events.error) {
|
||||||
@@ -1127,9 +1130,9 @@ var requirejs, require, define;
|
|||||||
//Use parentName here since the plugin's name is not reliable,
|
//Use parentName here since the plugin's name is not reliable,
|
||||||
//could be some weird string with no path that actually wants to
|
//could be some weird string with no path that actually wants to
|
||||||
//reference the parentName's path.
|
//reference the parentName's path.
|
||||||
plugin.load(map.name, makeRequire(map.parentMap, true, function (deps, cb) {
|
plugin.load(map.name, makeRequire(map.parentMap, true, function (deps, cb, er) {
|
||||||
deps.rjsSkipMap = true;
|
deps.rjsSkipMap = true;
|
||||||
return context.require(deps, cb);
|
return context.require(deps, cb, er);
|
||||||
}), load, config);
|
}), load, config);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -1209,7 +1212,7 @@ var requirejs, require, define;
|
|||||||
this.check();
|
this.check();
|
||||||
},
|
},
|
||||||
|
|
||||||
on: function(name, cb) {
|
on: function (name, cb) {
|
||||||
var cbs = this.events[name];
|
var cbs = this.events[name];
|
||||||
if (!cbs) {
|
if (!cbs) {
|
||||||
cbs = this.events[name] = [];
|
cbs = this.events[name] = [];
|
||||||
@@ -1362,7 +1365,12 @@ var requirejs, require, define;
|
|||||||
//update the maps for them, since their info, like URLs to load,
|
//update the maps for them, since their info, like URLs to load,
|
||||||
//may have changed.
|
//may have changed.
|
||||||
eachProp(registry, function (mod, id) {
|
eachProp(registry, function (mod, id) {
|
||||||
mod.map = makeModuleMap(id);
|
//If module already has init called, since it is too
|
||||||
|
//late to modify them, and ignore unnormalized ones
|
||||||
|
//since they are transient.
|
||||||
|
if (!mod.inited && !mod.map.unnormalized) {
|
||||||
|
mod.map = makeModuleMap(id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//If a deps array or a config callback is specified, then call
|
//If a deps array or a config callback is specified, then call
|
||||||
@@ -1471,6 +1479,10 @@ var requirejs, require, define;
|
|||||||
},
|
},
|
||||||
|
|
||||||
undef: function (id) {
|
undef: function (id) {
|
||||||
|
//Bind any waiting define() calls to this context,
|
||||||
|
//fix for #408
|
||||||
|
takeGlobalQueue();
|
||||||
|
|
||||||
var map = makeModuleMap(id, null, true),
|
var map = makeModuleMap(id, null, true),
|
||||||
mod = registry[id];
|
mod = registry[id];
|
||||||
|
|
||||||
@@ -1509,9 +1521,9 @@ var requirejs, require, define;
|
|||||||
* @param {String} moduleName the name of the module to potentially complete.
|
* @param {String} moduleName the name of the module to potentially complete.
|
||||||
*/
|
*/
|
||||||
completeLoad: function (moduleName) {
|
completeLoad: function (moduleName) {
|
||||||
var shim = config.shim[moduleName] || {},
|
var found, args, mod,
|
||||||
shExports = shim.exports && shim.exports.exports,
|
shim = config.shim[moduleName] || {},
|
||||||
found, args, mod;
|
shExports = shim.exports && shim.exports.exports;
|
||||||
|
|
||||||
takeGlobalQueue();
|
takeGlobalQueue();
|
||||||
|
|
||||||
@@ -1538,9 +1550,7 @@ var requirejs, require, define;
|
|||||||
//of those calls/init calls changes the registry.
|
//of those calls/init calls changes the registry.
|
||||||
mod = registry[moduleName];
|
mod = registry[moduleName];
|
||||||
|
|
||||||
if (!found &&
|
if (!found && !defined[moduleName] && mod && !mod.inited) {
|
||||||
!defined[moduleName] &&
|
|
||||||
mod && !mod.inited) {
|
|
||||||
if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
|
if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
|
||||||
if (hasPathFallback(moduleName)) {
|
if (hasPathFallback(moduleName)) {
|
||||||
return;
|
return;
|
||||||
@@ -1633,7 +1643,8 @@ var requirejs, require, define;
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Join the path parts together, then figure out if baseUrl is needed.
|
//Join the path parts together, then figure out if baseUrl is needed.
|
||||||
url = syms.join('/') + (ext || '.js');
|
url = syms.join('/');
|
||||||
|
url += (ext || (/\?/.test(url) ? '' : '.js'));
|
||||||
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
|
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1670,7 +1681,7 @@ var requirejs, require, define;
|
|||||||
//all old browsers will be supported, but this one was easy enough
|
//all old browsers will be supported, but this one was easy enough
|
||||||
//to support and still makes sense.
|
//to support and still makes sense.
|
||||||
if (evt.type === 'load' ||
|
if (evt.type === 'load' ||
|
||||||
(readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
|
(readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
|
||||||
//Reset interactive script so a script node is not held onto for
|
//Reset interactive script so a script node is not held onto for
|
||||||
//to long.
|
//to long.
|
||||||
interactiveScript = null;
|
interactiveScript = null;
|
||||||
@@ -1710,8 +1721,8 @@ var requirejs, require, define;
|
|||||||
req = requirejs = function (deps, callback, errback, optional) {
|
req = requirejs = function (deps, callback, errback, optional) {
|
||||||
|
|
||||||
//Find the right context, use default
|
//Find the right context, use default
|
||||||
var contextName = defContextName,
|
var context, config,
|
||||||
context, config;
|
contextName = defContextName;
|
||||||
|
|
||||||
// Determine if have config object in the call.
|
// Determine if have config object in the call.
|
||||||
if (!isArray(deps) && typeof deps !== 'string') {
|
if (!isArray(deps) && typeof deps !== 'string') {
|
||||||
@@ -1810,8 +1821,8 @@ var requirejs, require, define;
|
|||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
//In the browser so use a script tag
|
//In the browser so use a script tag
|
||||||
node = config.xhtml ?
|
node = config.xhtml ?
|
||||||
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
|
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
|
||||||
document.createElement('script');
|
document.createElement('script');
|
||||||
node.type = config.scriptType || 'text/javascript';
|
node.type = config.scriptType || 'text/javascript';
|
||||||
node.charset = 'utf-8';
|
node.charset = 'utf-8';
|
||||||
node.async = true;
|
node.async = true;
|
||||||
@@ -1828,15 +1839,15 @@ var requirejs, require, define;
|
|||||||
//UNFORTUNATELY Opera implements attachEvent but does not follow the script
|
//UNFORTUNATELY Opera implements attachEvent but does not follow the script
|
||||||
//script execution mode.
|
//script execution mode.
|
||||||
if (node.attachEvent &&
|
if (node.attachEvent &&
|
||||||
//Check if node.attachEvent is artificially added by custom script or
|
//Check if node.attachEvent is artificially added by custom script or
|
||||||
//natively supported by browser
|
//natively supported by browser
|
||||||
//read https://github.com/jrburke/requirejs/issues/187
|
//read https://github.com/jrburke/requirejs/issues/187
|
||||||
//if we can NOT find [native code] then it must NOT natively supported.
|
//if we can NOT find [native code] then it must NOT natively supported.
|
||||||
//in IE8, node.attachEvent does not have toString()
|
//in IE8, node.attachEvent does not have toString()
|
||||||
//Note the test for "[native code" with no closing brace, see:
|
//Note the test for "[native code" with no closing brace, see:
|
||||||
//https://github.com/jrburke/requirejs/issues/273
|
//https://github.com/jrburke/requirejs/issues/273
|
||||||
!(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
|
!(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
|
||||||
!isOpera) {
|
!isOpera) {
|
||||||
//Probably IE. IE (at least 6-8) do not fire
|
//Probably IE. IE (at least 6-8) do not fire
|
||||||
//script onload right after executing the script, so
|
//script onload right after executing the script, so
|
||||||
//we cannot tie the anonymous define call to a name.
|
//we cannot tie the anonymous define call to a name.
|
||||||
|
|||||||
12
vendor/underscore/test/collections.js
vendored
12
vendor/underscore/test/collections.js
vendored
@@ -253,6 +253,18 @@ $(document).ready(function() {
|
|||||||
equal(grouped['5'].join(' '), 'three seven eight');
|
equal(grouped['5'].join(' '), 'three seven eight');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('collections: countBy', function() {
|
||||||
|
var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; });
|
||||||
|
equal(parity['true'], 2);
|
||||||
|
equal(parity['false'], 3);
|
||||||
|
|
||||||
|
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
|
||||||
|
var grouped = _.countBy(list, 'length');
|
||||||
|
equal(grouped['3'], 4);
|
||||||
|
equal(grouped['4'], 3);
|
||||||
|
equal(grouped['5'], 3);
|
||||||
|
});
|
||||||
|
|
||||||
test('collections: sortedIndex', function() {
|
test('collections: sortedIndex', function() {
|
||||||
var numbers = [10, 20, 30, 40, 50], num = 35;
|
var numbers = [10, 20, 30, 40, 50], num = 35;
|
||||||
var indexForNum = _.sortedIndex(numbers, num);
|
var indexForNum = _.sortedIndex(numbers, num);
|
||||||
|
|||||||
32
vendor/underscore/underscore-min.js
vendored
Normal file
32
vendor/underscore/underscore-min.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Underscore.js 1.3.3
|
||||||
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
|
// Underscore may be freely distributed under the MIT license.
|
||||||
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||||
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||||
|
// For all details and documentation:
|
||||||
|
// http://documentcloud.github.com/underscore
|
||||||
|
(function(){var s=this,L=s._,p={},k=Array.prototype,q=Object.prototype,M=k.push,i=k.slice,N=k.unshift,m=q.toString,O=q.hasOwnProperty,z=k.forEach,A=k.map,B=k.reduce,C=k.reduceRight,D=k.filter,E=k.every,F=k.some,r=k.indexOf,G=k.lastIndexOf,q=Array.isArray,P=Object.keys,t=Function.prototype.bind,b=function(a){return new l(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,c,
|
||||||
|
d){if(a!=null)if(z&&a.forEach===z)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(c.call(d,a[e],e,a)===p)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===p)break};b.map=b.collect=function(a,c,d){var b=[];if(a==null)return b;if(A&&a.map===A)return a.map(c,d);j(a,function(a,g,h){b[b.length]=c.call(d,a,g,h)});return b};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduce===B){e&&(c=b.bind(c,e));return f?a.reduce(c,
|
||||||
|
d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(C&&a.reduceRight===C){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;H(a,function(a,g,h){if(c.call(b,a,g,h)){e=
|
||||||
|
a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(D&&a.filter===D)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(E&&a.every===E)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return p});return!!e};var H=b.some=b.any=
|
||||||
|
function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(F&&a.some===F)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return p});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(r&&a.indexOf===r)return a.indexOf(c)!=-1;return b=H(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};
|
||||||
|
b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});
|
||||||
|
return e.value};b.shuffle=function(a){var c,b=0,e=[];j(a,function(a){c=Math.floor(Math.random()*++b);e[b-1]=e[c];e[c]=a});return e};b.sortBy=function(a,c,d){var e=I(a,c);return b.pluck(b.map(a,function(a,c,b){return{value:a,criteria:e.call(d,a,c,b)}}).sort(function(a,c){var b=a.criteria,d=c.criteria;return b===void 0?1:d===void 0?-1:b<d?-1:b>d?1:0}),"value")};var I=function(a,c){return b.isFunction(c)?c:function(a){return a[c]}},J=function(a,c,b){var e={},f=I(a,c);j(a,function(a,c){var i=f(a,c);b(e,
|
||||||
|
i,a)});return e};b.groupBy=function(a,c){return J(a,c,function(a,c,b){(a[c]||(a[c]=[])).push(b)})};b.countBy=function(a,c){return J(a,c,function(a,c){a[c]||(a[c]=0);a[c]++})};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var c=d(c),e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<c?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=
|
||||||
|
b.take=function(a,c,b){return c!=null&&!b?i.call(a,0,c):a[0]};b.initial=function(a,c,b){return i.call(a,0,a.length-(c==null||b?1:c))};b.last=function(a,c,b){return c!=null&&!b?i.call(a,Math.max(a.length-c,0)):a[a.length-1]};b.rest=b.tail=function(a,c,b){return i.call(a,c==null||b?1:c)};b.compact=function(a){return b.filter(a,function(a){return!!a})};var n=function(a,c,d){j(a,function(a){b.isArray(a)?c?M.apply(d,a):n(a,c,d):d.push(a)});return d};b.flatten=function(a,c){return n(a,c,[])};b.without=
|
||||||
|
function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(n(arguments,true,[]))};b.intersection=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=n(i.call(arguments,1),true,[]);
|
||||||
|
return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.zipObject=function(a,c){for(var b={},e=0,f=a.length;e<f;e++)b[a[e]]=c[e];return b};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(r&&a.indexOf===r)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a==null)return-1;
|
||||||
|
if(G&&a.lastIndexOf===G)return a.lastIndexOf(c);for(var b=a.length;b--;)if(a[b]===c)return b;return-1};b.range=function(a,c,b){if(arguments.length<=1){c=a||0;a=0}for(var b=arguments[2]||1,e=Math.max(Math.ceil((c-a)/b),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+b}return g};var K=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));
|
||||||
|
K.prototype=a.prototype;var b=new K,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,c){var b=i.call(arguments,2);return setTimeout(function(){return a.apply(null,b)},c)};b.defer=function(a){return b.delay.apply(b,
|
||||||
|
[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));if(g)h=true;else{g=true;i=a.apply(d,e)}j();return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments,h=d&&!e;clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b);h&&a.apply(f,g)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;
|
||||||
|
return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=P||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=
|
||||||
|
function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var b={};j(n(i.call(arguments,1),true,[]),function(d){d in a&&(b[d]=a[d])});return b};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?
|
||||||
|
a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};var u=function(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=m.call(a);if(e!=m.call(c))return false;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==
|
||||||
|
+c;case "[object RegExp]":return a.source==c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){f=a.length;if(g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&u(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)){f++;if(!(g=b.has(c,h)&&
|
||||||
|
u(a[h],c[h],d)))break}if(g){for(h in c)if(b.has(c,h)&&!f--)break;g=!f}}d.pop();return g};b.isEqual=function(a,b){return u(a,b,[])};b.isEmpty=function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=q||function(a){return m.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};j("Arguments,Function,String,Number,Date,RegExp".split(","),function(a){b["is"+
|
||||||
|
a]=function(b){return m.call(b)=="[object "+a+"]"}});b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||m.call(a)=="[object Boolean]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return O.call(a,b)};b.noConflict=function(){s._=L;return this};b.identity=function(a){return a};
|
||||||
|
b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};var Q={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},R=/[&<>"'\/]/g;b.escape=function(a){return(""+a).replace(R,function(a){return Q[a]})};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){S(c,b[c]=a[c])})};var T=0;b.uniqueId=function(a){var b=T++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,
|
||||||
|
escape:/<%-([\s\S]+?)%>/g};var v=/.^/,o={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},w;for(w in o)o[o[w]]=w;var U=/\\|'|\r|\n|\t|\u2028|\u2029/g,V=/\\(\\|'|r|n|t|u2028|u2029)/g,x=function(a){return a.replace(V,function(a,b){return o[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(U,function(a){return"\\"+o[a]}).replace(d.escape||v,function(a,b){return"'+\n((__t=("+x(b)+"))==null?'':_.escape(__t))+\n'"}).replace(d.interpolate||
|
||||||
|
v,function(a,b){return"'+\n((__t=("+x(b)+"))==null?'':__t)+\n'"}).replace(d.evaluate||v,function(a,b){return"';\n"+x(b)+"\n__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};b.chain=function(a){return b(a).chain()};
|
||||||
|
var l=function(a){this._wrapped=a};b.prototype=l.prototype;var y=function(a,c){return c?b(a).chain():a},S=function(a,c){l.prototype[a]=function(){var a=i.call(arguments);N.call(a,this._wrapped);return y(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];l.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);(a=="shift"||a=="splice")&&d.length===0&&delete d[0];return y(d,this._chain)}});j(["concat","join","slice"],function(a){var b=
|
||||||
|
k[a];l.prototype[a]=function(){return y(b.apply(this._wrapped,arguments),this._chain)}});l.prototype.chain=function(){this._chain=true;return this};l.prototype.value=function(){return this._wrapped}}).call(this);
|
||||||
47
vendor/underscore/underscore.js
vendored
47
vendor/underscore/underscore.js
vendored
@@ -1,6 +1,6 @@
|
|||||||
// Underscore.js 1.3.3
|
// Underscore.js 1.3.3
|
||||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||||
// Underscore is freely distributable under the MIT license.
|
// Underscore may be freely distributed under the MIT license.
|
||||||
// Portions of Underscore are inspired or borrowed from Prototype,
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||||
// For all details and documentation:
|
// For all details and documentation:
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
|
|
||||||
// Sort the object's values by a criterion produced by an iterator.
|
// Sort the object's values by a criterion produced by an iterator.
|
||||||
_.sortBy = function(obj, val, context) {
|
_.sortBy = function(obj, val, context) {
|
||||||
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
var iterator = lookupIterator(obj, val);
|
||||||
return _.pluck(_.map(obj, function(value, index, list) {
|
return _.pluck(_.map(obj, function(value, index, list) {
|
||||||
return {
|
return {
|
||||||
value : value,
|
value : value,
|
||||||
@@ -281,16 +281,38 @@
|
|||||||
}), 'value');
|
}), 'value');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An internal function to generate lookup iterators.
|
||||||
|
var lookupIterator = function(obj, val) {
|
||||||
|
return _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
// An internal function used for aggregate "group by" operations.
|
||||||
|
var group = function(obj, val, behavior) {
|
||||||
|
var result = {};
|
||||||
|
var iterator = lookupIterator(obj, val);
|
||||||
|
each(obj, function(value, index) {
|
||||||
|
var key = iterator(value, index);
|
||||||
|
behavior(result, key, value);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// Groups the object's values by a criterion. Pass either a string attribute
|
// Groups the object's values by a criterion. Pass either a string attribute
|
||||||
// to group by, or a function that returns the criterion.
|
// to group by, or a function that returns the criterion.
|
||||||
_.groupBy = function(obj, val) {
|
_.groupBy = function(obj, val) {
|
||||||
var result = {};
|
return group(obj, val, function(result, key, value) {
|
||||||
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
|
||||||
each(obj, function(value, index) {
|
|
||||||
var key = iterator(value, index);
|
|
||||||
(result[key] || (result[key] = [])).push(value);
|
(result[key] || (result[key] = [])).push(value);
|
||||||
});
|
});
|
||||||
return result;
|
};
|
||||||
|
|
||||||
|
// 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 = function(obj, val) {
|
||||||
|
return group(obj, val, function(result, key, value) {
|
||||||
|
result[key] || (result[key] = 0);
|
||||||
|
result[key]++;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use a comparator function to figure out the smallest index at which
|
// Use a comparator function to figure out the smallest index at which
|
||||||
@@ -308,10 +330,9 @@
|
|||||||
|
|
||||||
// Safely convert anything iterable into a real, live array.
|
// Safely convert anything iterable into a real, live array.
|
||||||
_.toArray = function(obj) {
|
_.toArray = function(obj) {
|
||||||
if (!obj) return [];
|
if (!obj) return [];
|
||||||
if (_.isArray(obj)) return slice.call(obj);
|
if (_.isArray(obj) || _.isArguments(obj)) return slice.call(obj);
|
||||||
if (_.isArguments(obj)) return slice.call(obj);
|
if (_.isFunction(obj.toArray)) return obj.toArray();
|
||||||
if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
|
|
||||||
return _.values(obj);
|
return _.values(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -709,7 +730,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Internal recursive comparison function for `isEqual`.
|
// Internal recursive comparison function for `isEqual`.
|
||||||
function eq(a, b, stack) {
|
var eq = function(a, b, stack) {
|
||||||
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||||||
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
||||||
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||||
@@ -794,7 +815,7 @@
|
|||||||
// Remove the first object from the stack of traversed objects.
|
// Remove the first object from the stack of traversed objects.
|
||||||
stack.pop();
|
stack.pop();
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Perform a deep comparison to check if two objects are equal.
|
// Perform a deep comparison to check if two objects are equal.
|
||||||
_.isEqual = function(a, b) {
|
_.isEqual = function(a, b) {
|
||||||
|
|||||||
Reference in New Issue
Block a user