mirror of
https://github.com/atlanticbiomedical/biomedjs.git
synced 2025-07-02 00:47:26 -04:00
Added node-modules
This commit is contained in:
8
node_modules/piler/node_modules/underscore.string/.travis.yml
generated
vendored
Normal file
8
node_modules/piler/node_modules/underscore.string/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- 1.9.3
|
||||
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- sleep 2
|
5
node_modules/piler/node_modules/underscore.string/Gemfile
generated
vendored
Normal file
5
node_modules/piler/node_modules/underscore.string/Gemfile
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
source :rubygems
|
||||
|
||||
gem 'serve'
|
||||
gem 'uglifier'
|
||||
gem 'rake'
|
34
node_modules/piler/node_modules/underscore.string/Gemfile.lock
generated
vendored
Normal file
34
node_modules/piler/node_modules/underscore.string/Gemfile.lock
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.2.3)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
execjs (1.3.0)
|
||||
multi_json (~> 1.0)
|
||||
i18n (0.6.0)
|
||||
multi_json (1.2.0)
|
||||
rack (1.4.1)
|
||||
rack-test (0.6.1)
|
||||
rack (>= 1.0)
|
||||
rake (0.9.2.2)
|
||||
serve (1.5.1)
|
||||
activesupport (~> 3.0)
|
||||
i18n
|
||||
rack (~> 1.2)
|
||||
rack-test (~> 0.5)
|
||||
tilt (~> 1.3)
|
||||
tzinfo
|
||||
tilt (1.3.3)
|
||||
tzinfo (0.3.33)
|
||||
uglifier (1.2.4)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (>= 1.0.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
rake
|
||||
serve
|
||||
uglifier
|
668
node_modules/piler/node_modules/underscore.string/README.markdown
generated
vendored
Normal file
668
node_modules/piler/node_modules/underscore.string/README.markdown
generated
vendored
Normal file
@ -0,0 +1,668 @@
|
||||
# Underscore.string [](http://travis-ci.org/epeli/underscore.string) #
|
||||
|
||||
|
||||
|
||||
Javascript lacks complete string manipulation operations.
|
||||
This an attempt to fill that gap. List of build-in methods can be found
|
||||
for example from [Dive Into JavaScript][d].
|
||||
|
||||
[d]: http://www.diveintojavascript.com/core-javascript-reference/the-string-object
|
||||
|
||||
|
||||
As name states this an extension for [Underscore.js][u], but it can be used
|
||||
independently from **_s**-global variable. But with Underscore.js you can
|
||||
use Object-Oriented style and chaining:
|
||||
|
||||
[u]: http://documentcloud.github.com/underscore/
|
||||
|
||||
```javascript
|
||||
_(" epeli ").chain().trim().capitalize().value()
|
||||
=> "Epeli"
|
||||
```
|
||||
|
||||
## Download ##
|
||||
|
||||
* [Development version](https://raw.github.com/epeli/underscore.string/master/lib/underscore.string.js) *Uncompressed with Comments 18kb*
|
||||
* [Production version](https://github.com/epeli/underscore.string/raw/master/dist/underscore.string.min.js) *Minified 7kb*
|
||||
|
||||
|
||||
## Node.js installation ##
|
||||
|
||||
**npm package**
|
||||
|
||||
npm install underscore.string
|
||||
|
||||
**Standalone usage**:
|
||||
|
||||
```javascript
|
||||
var _s = require('underscore.string');
|
||||
```
|
||||
|
||||
**Integrate with Underscore.js**:
|
||||
|
||||
```javascript
|
||||
var _ = require('underscore');
|
||||
|
||||
// Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)
|
||||
_.str = require('underscore.string');
|
||||
|
||||
// Mix in non-conflict functions to Underscore namespace if you want
|
||||
_.mixin(_.str.exports());
|
||||
|
||||
// All functions, include conflict, will be available through _.str object
|
||||
_.str.include('Underscore.string', 'string'); // => true
|
||||
```
|
||||
|
||||
## String Functions ##
|
||||
|
||||
For availability of functions in this way you need to mix in Underscore.string functions:
|
||||
|
||||
```javascript
|
||||
_.mixin(_.string.exports());
|
||||
```
|
||||
|
||||
otherwise functions from examples will be available through _.string or _.str objects:
|
||||
|
||||
```javascript
|
||||
_.str.capitalize('epeli')
|
||||
=> "Epeli"
|
||||
```
|
||||
|
||||
**capitalize** _.capitalize(string)
|
||||
|
||||
Converts first letter of the string to uppercase.
|
||||
|
||||
```javascript
|
||||
_.capitalize("foo Bar")
|
||||
=> "Foo Bar"
|
||||
```
|
||||
|
||||
**chop** _.chop(string, step)
|
||||
|
||||
```javascript
|
||||
_.chop('whitespace', 3)
|
||||
=> ['whi','tes','pac','e']
|
||||
```
|
||||
|
||||
**clean** _.clean(str)
|
||||
|
||||
Compress some whitespaces to one.
|
||||
|
||||
```javascript
|
||||
_.clean(" foo bar ")
|
||||
=> 'foo bar'
|
||||
```
|
||||
|
||||
**chars** _.chars(str)
|
||||
|
||||
```javascript
|
||||
_.chars('Hello')
|
||||
=> ['H','e','l','l','o']
|
||||
```
|
||||
|
||||
**includes** _.includes(string, substring)
|
||||
|
||||
Tests if string contains a substring.
|
||||
|
||||
```javascript
|
||||
_.includes("foobar", "ob")
|
||||
=> true
|
||||
```
|
||||
|
||||
**include** available only through _.str object, because Underscore has function with the same name.
|
||||
|
||||
```javascript
|
||||
_.str.include("foobar", "ob")
|
||||
=> true
|
||||
```
|
||||
|
||||
**includes** function was removed
|
||||
|
||||
But you can create it in this way, for compatibility with previous versions:
|
||||
|
||||
```javascript
|
||||
_.includes = _.str.include
|
||||
```
|
||||
|
||||
**count** _.count(string, substring)
|
||||
|
||||
```javascript
|
||||
_('Hello world').count('l')
|
||||
=> 3
|
||||
```
|
||||
|
||||
**escapeHTML** _.escapeHTML(string)
|
||||
|
||||
Converts HTML special characters to their entity equivalents.
|
||||
|
||||
```javascript
|
||||
_('<div>Blah blah blah</div>').escapeHTML();
|
||||
=> '<div>Blah blah blah</div>'
|
||||
```
|
||||
|
||||
**unescapeHTML** _.unescapeHTML(string)
|
||||
|
||||
Converts entity characters to HTML equivalents.
|
||||
|
||||
```javascript
|
||||
_('<div>Blah blah blah</div>').unescapeHTML();
|
||||
=> '<div>Blah blah blah</div>'
|
||||
```
|
||||
|
||||
**insert** _.insert(string, index, substing)
|
||||
|
||||
```javascript
|
||||
_('Hello ').insert(6, 'world')
|
||||
=> 'Hello world'
|
||||
```
|
||||
|
||||
**isBlank** _.isBlank(string)
|
||||
|
||||
```javascript
|
||||
_('').isBlank(); // => true
|
||||
_('\n').isBlank(); // => true
|
||||
_(' ').isBlank(); // => true
|
||||
_('a').isBlank(); // => false
|
||||
```
|
||||
|
||||
**join** _.join(separator, *strings)
|
||||
|
||||
Joins strings together with given separator
|
||||
|
||||
```javascript
|
||||
_.join(" ", "foo", "bar")
|
||||
=> "foo bar"
|
||||
```
|
||||
|
||||
**lines** _.lines(str)
|
||||
|
||||
```javascript
|
||||
_.lines("Hello\nWorld")
|
||||
=> ["Hello", "World"]
|
||||
```
|
||||
|
||||
**reverse** available only through _.str object, because Underscore has function with the same name.
|
||||
|
||||
Return reversed string:
|
||||
|
||||
```javascript
|
||||
_.str.reverse("foobar")
|
||||
=> 'raboof'
|
||||
```
|
||||
|
||||
**splice** _.splice(string, index, howmany, substring)
|
||||
|
||||
Like a array splice.
|
||||
|
||||
```javascript
|
||||
_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli')
|
||||
=> 'https://edtsech@bitbucket.org/epeli/underscore.strings'
|
||||
```
|
||||
|
||||
**startsWith** _.startsWith(string, starts)
|
||||
|
||||
This method checks whether string starts with starts.
|
||||
|
||||
```javascript
|
||||
_("image.gif").startsWith("image")
|
||||
=> true
|
||||
```
|
||||
|
||||
**endsWith** _.endsWith(string, ends)
|
||||
|
||||
This method checks whether string ends with ends.
|
||||
|
||||
```javascript
|
||||
_("image.gif").endsWith("gif")
|
||||
=> true
|
||||
```
|
||||
|
||||
**succ** _.succ(str)
|
||||
|
||||
Returns the successor to str.
|
||||
|
||||
```javascript
|
||||
_('a').succ()
|
||||
=> 'b'
|
||||
|
||||
_('A').succ()
|
||||
=> 'B'
|
||||
```
|
||||
|
||||
**supplant**
|
||||
|
||||
Supplant function was removed, use Underscore.js [template function][p].
|
||||
|
||||
[p]: http://documentcloud.github.com/underscore/#template
|
||||
|
||||
**strip** alias for *trim*
|
||||
|
||||
**lstrip** alias for *ltrim*
|
||||
|
||||
**rstrip** alias for *rtrim*
|
||||
|
||||
**titleize** _.titleize(string)
|
||||
|
||||
```javascript
|
||||
_('my name is epeli').titleize()
|
||||
=> 'My Name Is Epeli'
|
||||
```
|
||||
|
||||
**camelize** _.camelize(string)
|
||||
|
||||
Converts underscored or dasherized string to a camelized one
|
||||
|
||||
```javascript
|
||||
_('-moz-transform').camelize()
|
||||
=> 'MozTransform'
|
||||
```
|
||||
|
||||
**classify** _.classify(string)
|
||||
|
||||
Converts string to camelized class name
|
||||
|
||||
```javascript
|
||||
_('some_class_name').classify()
|
||||
=> 'SomeClassName'
|
||||
```
|
||||
|
||||
**underscored** _.underscored(string)
|
||||
|
||||
Converts a camelized or dasherized string into an underscored one
|
||||
|
||||
```javascript
|
||||
_('MozTransform').underscored()
|
||||
=> 'moz_transform'
|
||||
```
|
||||
|
||||
**dasherize** _.dasherize(string)
|
||||
|
||||
Converts a underscored or camelized string into an dasherized one
|
||||
|
||||
```javascript
|
||||
_('MozTransform').dasherize()
|
||||
=> '-moz-transform'
|
||||
```
|
||||
|
||||
**humanize** _.humanize(string)
|
||||
|
||||
Converts an underscored, camelized, or dasherized string into a humanized one.
|
||||
Also removes beginning and ending whitespace, and removes the postfix '_id'.
|
||||
|
||||
```javascript
|
||||
_(' capitalize dash-CamelCase_underscore trim ').humanize()
|
||||
=> 'Capitalize dash camel case underscore trim'
|
||||
```
|
||||
|
||||
**trim** _.trim(string, [characters])
|
||||
|
||||
trims defined characters from begining and ending of the string.
|
||||
Defaults to whitespace characters.
|
||||
|
||||
```javascript
|
||||
_.trim(" foobar ")
|
||||
=> "foobar"
|
||||
|
||||
_.trim("_-foobar-_", "_-")
|
||||
=> "foobar"
|
||||
```
|
||||
|
||||
|
||||
**ltrim** _.ltrim(string, [characters])
|
||||
|
||||
Left trim. Similar to trim, but only for left side.
|
||||
|
||||
|
||||
**rtrim** _.rtrim(string, [characters])
|
||||
|
||||
Right trim. Similar to trim, but only for right side.
|
||||
|
||||
**truncate** _.truncate(string, length, truncateString)
|
||||
|
||||
```javascript
|
||||
_('Hello world').truncate(5)
|
||||
=> 'Hello...'
|
||||
|
||||
_('Hello').truncate(10)
|
||||
=> 'Hello'
|
||||
```
|
||||
|
||||
**prune** _.prune(string, length, pruneString)
|
||||
|
||||
Elegant version of truncate.
|
||||
Makes sure the pruned string does not exceed the original length.
|
||||
Avoid half-chopped words when truncating.
|
||||
|
||||
```javascript
|
||||
_('Hello, world').prune(5)
|
||||
=> 'Hello...'
|
||||
|
||||
_('Hello, world').prune(8)
|
||||
=> 'Hello...'
|
||||
|
||||
_('Hello, world').prune(5, ' (read a lot more)')
|
||||
=> 'Hello, world' (as adding "(read a lot more)" would be longer than the original string)
|
||||
|
||||
_('Hello, cruel world').prune(15)
|
||||
=> 'Hello, cruel...'
|
||||
|
||||
_('Hello').prune(10)
|
||||
=> 'Hello'
|
||||
```
|
||||
|
||||
**words** _.words(str, delimiter=" ")
|
||||
|
||||
Split string by delimiter (String or RegExp), ' ' by default.
|
||||
|
||||
```javascript
|
||||
_.words("I love you")
|
||||
=> ["I","love","you"]
|
||||
|
||||
_.words("I_love_you", "_")
|
||||
=> ["I","love","you"]
|
||||
|
||||
_.words("I-love-you", /-/)
|
||||
=> ["I","love","you"]
|
||||
```
|
||||
|
||||
**sprintf** _.sprintf(string format, *arguments)
|
||||
|
||||
C like string formatting.
|
||||
Credits goes to [Alexandru Marasteanu][o].
|
||||
For more detailed documentation, see the [original page][o].
|
||||
|
||||
[o]: http://www.diveintojavascript.com/projects/sprintf-for-javascript
|
||||
|
||||
```javascript
|
||||
_.sprintf("%.1f", 1.17)
|
||||
"1.2"
|
||||
```
|
||||
|
||||
**pad** _.pad(str, length, [padStr, type])
|
||||
|
||||
pads the `str` with characters until the total string length is equal to the passed `length` parameter. By default, pads on the **left** with the space char (`" "`). `padStr` is truncated to a single character if necessary.
|
||||
|
||||
```javascript
|
||||
_.pad("1", 8)
|
||||
-> " 1";
|
||||
|
||||
_.pad("1", 8, '0')
|
||||
-> "00000001";
|
||||
|
||||
_.pad("1", 8, '0', 'right')
|
||||
-> "10000000";
|
||||
|
||||
_.pad("1", 8, '0', 'both')
|
||||
-> "00001000";
|
||||
|
||||
_.pad("1", 8, 'bleepblorp', 'both')
|
||||
-> "bbbb1bbb";
|
||||
```
|
||||
|
||||
**lpad** _.lpad(str, length, [padStr])
|
||||
|
||||
left-pad a string. Alias for `pad(str, length, padStr, 'left')`
|
||||
|
||||
```javascript
|
||||
_.lpad("1", 8, '0')
|
||||
-> "00000001";
|
||||
```
|
||||
|
||||
**rpad** _.rpad(str, length, [padStr])
|
||||
|
||||
right-pad a string. Alias for `pad(str, length, padStr, 'right')`
|
||||
|
||||
```javascript
|
||||
_.rpad("1", 8, '0')
|
||||
-> "10000000";
|
||||
```
|
||||
|
||||
**lrpad** _.lrpad(str, length, [padStr])
|
||||
|
||||
left/right-pad a string. Alias for `pad(str, length, padStr, 'both')`
|
||||
|
||||
```javascript
|
||||
_.lrpad("1", 8, '0')
|
||||
-> "00001000";
|
||||
```
|
||||
|
||||
**center** alias for **lrpad**
|
||||
|
||||
**ljust** alias for *rpad*
|
||||
|
||||
**rjust** alias for *lpad*
|
||||
|
||||
**toNumber** _.toNumber(string, [decimals])
|
||||
|
||||
Parse string to number. Returns NaN if string can't be parsed to number.
|
||||
|
||||
```javascript
|
||||
_('2.556').toNumber()
|
||||
=> 3
|
||||
|
||||
_('2.556').toNumber(1)
|
||||
=> 2.6
|
||||
```
|
||||
|
||||
**strRight** _.strRight(string, pattern)
|
||||
|
||||
Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.
|
||||
|
||||
```javascript
|
||||
_('This_is_a_test_string').strRight('_')
|
||||
=> "is_a_test_string";
|
||||
```
|
||||
|
||||
**strRightBack** _.strRightBack(string, pattern)
|
||||
|
||||
Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the right of the pattern or all string if no match found.
|
||||
|
||||
```javascript
|
||||
_('This_is_a_test_string').strRightBack('_')
|
||||
=> "string";
|
||||
```
|
||||
|
||||
**strLeft** _.strLeft(string, pattern)
|
||||
|
||||
Searches a string from left to right for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.
|
||||
|
||||
```javascript
|
||||
_('This_is_a_test_string').strLeft('_')
|
||||
=> "This";
|
||||
```
|
||||
|
||||
**strLeftBack** _.strLeftBack(string, pattern)
|
||||
|
||||
Searches a string from right to left for a pattern and returns a substring consisting of the characters in the string that are to the left of the pattern or all string if no match found.
|
||||
|
||||
```javascript
|
||||
_('This_is_a_test_string').strLeftBack('_')
|
||||
=> "This_is_a_test";
|
||||
```
|
||||
|
||||
**stripTags**
|
||||
|
||||
Removes all html tags from string.
|
||||
|
||||
```javascript
|
||||
_('a <a href="#">link</a>').stripTags()
|
||||
=> 'a link'
|
||||
|
||||
_('a <a href="#">link</a><script>alert("hello world!")</script>').stripTags()
|
||||
=> 'a linkalert("hello world!")'
|
||||
```
|
||||
|
||||
**toSentence** _.toSentence(array, [delimiter, lastDelimiter])
|
||||
|
||||
Join an array into a human readable sentence.
|
||||
|
||||
```javascript
|
||||
_.toSentence(['jQuery', 'Mootools', 'Prototype'])
|
||||
=> 'jQuery, Mootools and Prototype';
|
||||
|
||||
_.toSentence(['jQuery', 'Mootools', 'Prototype'], ', ', ' unt ')
|
||||
=> 'jQuery, Mootools unt Prototype';
|
||||
```
|
||||
|
||||
**repeat** _.repeat(string, count, [separator])
|
||||
|
||||
Repeats a string count times.
|
||||
|
||||
```javascript
|
||||
_.repeat("foo", 3)
|
||||
=> 'foofoofoo';
|
||||
|
||||
_.repeat("foo", 3, "bar")
|
||||
=> 'foobarfoobarfoo'
|
||||
```
|
||||
|
||||
**slugify** _.slugify(string)
|
||||
|
||||
Transform text into a URL slug. Replaces whitespaces, accentuated, and special characters with a dash.
|
||||
|
||||
```javascript
|
||||
_.slugify("Un éléphant à l'orée du bois")
|
||||
=> 'un-elephant-a-loree-du-bois';
|
||||
```
|
||||
|
||||
***Caution: this function is charset dependent***
|
||||
|
||||
## Roadmap ##
|
||||
|
||||
Any suggestions or bug reports are welcome. Just email me or more preferably open an issue.
|
||||
|
||||
## Changelog ##
|
||||
|
||||
### 2.0.0 ###
|
||||
|
||||
* Added prune, humanize functions
|
||||
* Added _.string (_.str) namespace for Underscore.string library
|
||||
* Removed includes function
|
||||
|
||||
#### Problems
|
||||
|
||||
We lose two things for `include` and `reverse` methods from `_.string`:
|
||||
|
||||
* Calls like `_('foobar').include('bar')` aren't available;
|
||||
* Chaining isn't available too.
|
||||
|
||||
But if you need this functionality you can create aliases for conflict functions which will be convenient for you:
|
||||
|
||||
```javascript
|
||||
_.mixin({
|
||||
includeString: _.str.include,
|
||||
reverseString: _.str.reverse
|
||||
})
|
||||
|
||||
// Now wrapper calls and chaining are available.
|
||||
_('foobar').chain().reverseString().includeString('rab').value()
|
||||
```
|
||||
|
||||
#### Standalone Usage
|
||||
|
||||
If you are using Underscore.string without Underscore. You also have `_.string` namespace for it and `_.str` alias
|
||||
But of course you can just reassign `_` variable with `_.string`
|
||||
|
||||
```javascript
|
||||
_ = _.string
|
||||
```
|
||||
### 2.2.0 ###
|
||||
|
||||
* Capitalize method behavior changed
|
||||
* Various perfomance tweaks
|
||||
|
||||
### 2.1.1###
|
||||
|
||||
* Fixed words method bug
|
||||
* Added classify method
|
||||
|
||||
### 2.1.0 ###
|
||||
|
||||
* AMD support
|
||||
* Added toSentence method
|
||||
* Added slugify method
|
||||
* Lots of speed optimizations
|
||||
|
||||
### 2.0.0 ###
|
||||
|
||||
For upgrading to this version you need to mix in Underscore.string library to Underscore object:
|
||||
|
||||
```javascript
|
||||
_.mixin(_.string.exports());
|
||||
```
|
||||
|
||||
and all non-conflict Underscore.string functions will be available through Underscore object.
|
||||
Also function `includes` has been removed, you should replace this function by `_.str.include`
|
||||
or create alias `_.includes = _.str.include` and all your code will work fine.
|
||||
|
||||
### 1.1.6 ###
|
||||
|
||||
* Fixed reverse and truncate
|
||||
* Added isBlank, stripTags, inlude(alias for includes)
|
||||
* Added uglifier compression
|
||||
|
||||
### 1.1.5 ###
|
||||
|
||||
* Added strRight, strRightBack, strLeft, strLeftBack
|
||||
|
||||
### 1.1.4 ###
|
||||
|
||||
* Added pad, lpad, rpad, lrpad methods and aliases center, ljust, rjust
|
||||
* Integration with Underscore 1.1.6
|
||||
|
||||
### 1.1.3 ###
|
||||
|
||||
* Added methods: underscored, camelize, dasherize
|
||||
* Support newer version of npm
|
||||
|
||||
### 1.1.2 ###
|
||||
|
||||
* Created functions: lines, chars, words functions
|
||||
|
||||
### 1.0.2 ###
|
||||
|
||||
* Created integration test suite with underscore.js 1.1.4 (now it's absolutely compatible)
|
||||
* Removed 'reverse' function, because this function override underscore.js 'reverse'
|
||||
|
||||
## Contribute ##
|
||||
|
||||
* Fork & pull request. Don't forget about tests.
|
||||
* If you planning add some feature please create issue before.
|
||||
|
||||
Otherwise changes will be rejected.
|
||||
|
||||
## Contributors list ##
|
||||
|
||||
* Esa-Matti Suuronen <esa-matti@suuronen.org> (<http://esa-matti.suuronen.org/>),
|
||||
* Edward Tsech <edtsech@gmail.com>,
|
||||
* Sasha Koss <kossnocorp@gmail.com> (<http://koss.nocorp.me/>),
|
||||
* Vladimir Dronnikov <dronnikov@gmail.com>,
|
||||
* Pete Kruckenberg (<https://github.com/kruckenb>),
|
||||
* Paul Chavard <paul@chavard.net> (<http://tchak.net>),
|
||||
* Ed Finkler <coj@funkatron.com> (<http://funkatron.com>)
|
||||
* Pavel Pravosud <rwz@duckroll.ru>
|
||||
* Anton Lindqvist <anton@qvister.se> (<http://qvister.se>)
|
||||
|
||||
## Licence ##
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2011 Esa-Matti Suuronen esa-matti@suuronen.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
28
node_modules/piler/node_modules/underscore.string/Rakefile
generated
vendored
Normal file
28
node_modules/piler/node_modules/underscore.string/Rakefile
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# encoding: utf-8
|
||||
task default: :test
|
||||
|
||||
desc 'Use UglifyJS to compress Underscore.string'
|
||||
task :build do
|
||||
require 'uglifier'
|
||||
source = File.read('lib/underscore.string.js')
|
||||
compressed = Uglifier.compile(source, copyright: false)
|
||||
File.open('dist/underscore.string.min.js', 'w'){ |f| f.write compressed }
|
||||
compression_rate = compressed.length.to_f/source.length
|
||||
puts "compressed dist/underscore.string.min.js: #{compressed.length}/#{source.length} #{(compression_rate * 100).round}%"
|
||||
end
|
||||
|
||||
desc 'Run tests'
|
||||
task :test do
|
||||
pid = spawn('bundle exec serve', err: '/dev/null')
|
||||
sleep 2
|
||||
|
||||
puts "Running underscore.string test suite."
|
||||
result1 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test.html"}
|
||||
|
||||
puts "Running Underscore test suite."
|
||||
result2 = system %{phantomjs ./test/run-qunit.js "http://localhost:4000/test/test_underscore/test.html"}
|
||||
|
||||
Process.kill 'INT', pid
|
||||
|
||||
exit(result1 && result2 ? 0 : 1)
|
||||
end
|
1
node_modules/piler/node_modules/underscore.string/dist/underscore.string.min.js
generated
vendored
Normal file
1
node_modules/piler/node_modules/underscore.string/dist/underscore.string.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
10
node_modules/piler/node_modules/underscore.string/foo.js
generated
vendored
Normal file
10
node_modules/piler/node_modules/underscore.string/foo.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
function boolMatch(s, matchers) {
|
||||
var i, matcher, down = s.toLowerCase();
|
||||
matchers = [].concat(matchers);
|
||||
for (i = 0; i < matchers.length; i += 1) {
|
||||
matcher = matchers[i];
|
||||
if (matcher.test && matcher.test(s)) return true;
|
||||
if (matcher && matcher.toLowerCase() === down) return true;
|
||||
}
|
||||
}
|
525
node_modules/piler/node_modules/underscore.string/lib/underscore.string.js
generated
vendored
Normal file
525
node_modules/piler/node_modules/underscore.string/lib/underscore.string.js
generated
vendored
Normal file
@ -0,0 +1,525 @@
|
||||
// Underscore.string
|
||||
// (c) 2010 Esa-Matti Suuronen <esa-matti aet suuronen dot org>
|
||||
// Underscore.strings is freely distributable under the terms of the MIT license.
|
||||
// Documentation: https://github.com/epeli/underscore.string
|
||||
// Some code is borrowed from MooTools and Alexandru Marasteanu.
|
||||
|
||||
// Version 2.2.0rc
|
||||
|
||||
(function(root){
|
||||
'use strict';
|
||||
|
||||
// Defining helper functions.
|
||||
|
||||
var nativeTrim = String.prototype.trim;
|
||||
var nativeTrimRight = String.prototype.trimRight;
|
||||
var nativeTrimLeft = String.prototype.trimLeft;
|
||||
|
||||
var parseNumber = function(source) { return source * 1 || 0; };
|
||||
|
||||
var strRepeat = function(str, qty, separator){
|
||||
// ~~var — is the fastest available way to convert anything to Integer in javascript.
|
||||
// We'll use it extensively in this lib.
|
||||
str += ''; qty = ~~qty;
|
||||
for (var repeat = []; qty > 0; repeat[--qty] = str) {}
|
||||
return repeat.join(separator == null ? '' : separator);
|
||||
};
|
||||
|
||||
var slice = function(a){
|
||||
return Array.prototype.slice.call(a);
|
||||
};
|
||||
|
||||
var defaultToWhiteSpace = function(characters){
|
||||
if (characters != null) {
|
||||
return '[' + _s.escapeRegExp(''+characters) + ']';
|
||||
}
|
||||
return '\\s';
|
||||
};
|
||||
|
||||
var escapeChars = {
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
quot: '"',
|
||||
apos: "'",
|
||||
amp: '&'
|
||||
};
|
||||
|
||||
var reversedEscapeChars = {};
|
||||
for(var key in escapeChars){ reversedEscapeChars[escapeChars[key]] = key; }
|
||||
|
||||
// sprintf() for JavaScript 0.7-beta1
|
||||
// http://www.diveintojavascript.com/projects/javascript-sprintf
|
||||
//
|
||||
// Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
|
||||
// All rights reserved.
|
||||
|
||||
var sprintf = (function() {
|
||||
function get_type(variable) {
|
||||
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
|
||||
}
|
||||
|
||||
var str_repeat = strRepeat;
|
||||
|
||||
var str_format = function() {
|
||||
if (!str_format.cache.hasOwnProperty(arguments[0])) {
|
||||
str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
|
||||
}
|
||||
return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
|
||||
};
|
||||
|
||||
str_format.format = function(parse_tree, argv) {
|
||||
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
|
||||
for (i = 0; i < tree_length; i++) {
|
||||
node_type = get_type(parse_tree[i]);
|
||||
if (node_type === 'string') {
|
||||
output.push(parse_tree[i]);
|
||||
}
|
||||
else if (node_type === 'array') {
|
||||
match = parse_tree[i]; // convenience purposes only
|
||||
if (match[2]) { // keyword argument
|
||||
arg = argv[cursor];
|
||||
for (k = 0; k < match[2].length; k++) {
|
||||
if (!arg.hasOwnProperty(match[2][k])) {
|
||||
throw new Error(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
|
||||
}
|
||||
arg = arg[match[2][k]];
|
||||
}
|
||||
} else if (match[1]) { // positional argument (explicit)
|
||||
arg = argv[match[1]];
|
||||
}
|
||||
else { // positional argument (implicit)
|
||||
arg = argv[cursor++];
|
||||
}
|
||||
|
||||
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
|
||||
throw new Error(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
|
||||
}
|
||||
switch (match[8]) {
|
||||
case 'b': arg = arg.toString(2); break;
|
||||
case 'c': arg = String.fromCharCode(arg); break;
|
||||
case 'd': arg = parseInt(arg, 10); break;
|
||||
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
|
||||
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
|
||||
case 'o': arg = arg.toString(8); break;
|
||||
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
|
||||
case 'u': arg = Math.abs(arg); break;
|
||||
case 'x': arg = arg.toString(16); break;
|
||||
case 'X': arg = arg.toString(16).toUpperCase(); break;
|
||||
}
|
||||
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
|
||||
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
|
||||
pad_length = match[6] - String(arg).length;
|
||||
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
|
||||
output.push(match[5] ? arg + pad : pad + arg);
|
||||
}
|
||||
}
|
||||
return output.join('');
|
||||
};
|
||||
|
||||
str_format.cache = {};
|
||||
|
||||
str_format.parse = function(fmt) {
|
||||
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
|
||||
while (_fmt) {
|
||||
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
|
||||
parse_tree.push(match[0]);
|
||||
}
|
||||
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
|
||||
parse_tree.push('%');
|
||||
}
|
||||
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
|
||||
if (match[2]) {
|
||||
arg_names |= 1;
|
||||
var field_list = [], replacement_field = match[2], field_match = [];
|
||||
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
||||
field_list.push(field_match[1]);
|
||||
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
|
||||
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
|
||||
field_list.push(field_match[1]);
|
||||
}
|
||||
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
|
||||
field_list.push(field_match[1]);
|
||||
}
|
||||
else {
|
||||
throw new Error('[_.sprintf] huh?');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('[_.sprintf] huh?');
|
||||
}
|
||||
match[2] = field_list;
|
||||
}
|
||||
else {
|
||||
arg_names |= 2;
|
||||
}
|
||||
if (arg_names === 3) {
|
||||
throw new Error('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
|
||||
}
|
||||
parse_tree.push(match);
|
||||
}
|
||||
else {
|
||||
throw new Error('[_.sprintf] huh?');
|
||||
}
|
||||
_fmt = _fmt.substring(match[0].length);
|
||||
}
|
||||
return parse_tree;
|
||||
};
|
||||
|
||||
return str_format;
|
||||
})();
|
||||
|
||||
|
||||
|
||||
// Defining underscore.string
|
||||
|
||||
var _s = {
|
||||
|
||||
VERSION: '2.2.0rc',
|
||||
|
||||
isBlank: function(str){
|
||||
return (/^\s*$/).test(str);
|
||||
},
|
||||
|
||||
stripTags: function(str){
|
||||
return (''+str).replace(/<\/?[^>]+>/g, '');
|
||||
},
|
||||
|
||||
capitalize : function(str) {
|
||||
str += '';
|
||||
return str.charAt(0).toUpperCase() + str.substring(1);
|
||||
},
|
||||
|
||||
chop: function(str, step){
|
||||
str = str+'';
|
||||
step = ~~step || str.length;
|
||||
var arr = [];
|
||||
for (var i = 0; i < str.length; i += step)
|
||||
arr.push(str.slice(i,i + step));
|
||||
return arr;
|
||||
},
|
||||
|
||||
clean: function(str){
|
||||
return _s.strip(str).replace(/\s+/g, ' ');
|
||||
},
|
||||
|
||||
count: function(str, substr){
|
||||
str += ''; substr += '';
|
||||
return str.split(substr).length - 1;
|
||||
},
|
||||
|
||||
chars: function(str) {
|
||||
return (''+str).split('');
|
||||
},
|
||||
|
||||
escapeHTML: function(str) {
|
||||
return (''+str).replace(/[&<>"']/g, function(match){ return '&' + reversedEscapeChars[match] + ';'; });
|
||||
},
|
||||
|
||||
unescapeHTML: function(str) {
|
||||
return (''+str).replace(/\&([^;]+);/g, function(entity, entityCode){
|
||||
var match;
|
||||
|
||||
if (entityCode in escapeChars) {
|
||||
return escapeChars[entityCode];
|
||||
} else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
|
||||
return String.fromCharCode(parseInt(match[1], 16));
|
||||
} else if (match = entityCode.match(/^#(\d+)$/)) {
|
||||
return String.fromCharCode(~~match[1]);
|
||||
} else {
|
||||
return entity;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
escapeRegExp: function(str){
|
||||
// From MooTools core 1.2.4
|
||||
return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
|
||||
},
|
||||
|
||||
insert: function(str, i, substr){
|
||||
var arr = _s.chars(str);
|
||||
arr.splice(~~i, 0, ''+substr);
|
||||
return arr.join('');
|
||||
},
|
||||
|
||||
include: function(str, needle){
|
||||
return !!~(''+str).indexOf(needle);
|
||||
},
|
||||
|
||||
join: function() {
|
||||
var args = slice(arguments);
|
||||
return args.join(args.shift());
|
||||
},
|
||||
|
||||
lines: function(str) {
|
||||
return (''+str).split("\n");
|
||||
},
|
||||
|
||||
reverse: function(str){
|
||||
return _s.chars(str).reverse().join('');
|
||||
},
|
||||
|
||||
splice: function(str, i, howmany, substr){
|
||||
var arr = _s.chars(str);
|
||||
arr.splice(~~i, ~~howmany, substr);
|
||||
return arr.join('');
|
||||
},
|
||||
|
||||
startsWith: function(str, starts){
|
||||
str += ''; starts += '';
|
||||
return str.length >= starts.length && str.substring(0, starts.length) === starts;
|
||||
},
|
||||
|
||||
endsWith: function(str, ends){
|
||||
str += ''; ends += '';
|
||||
return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
|
||||
},
|
||||
|
||||
succ: function(str){
|
||||
str += '';
|
||||
var arr = _s.chars(str);
|
||||
arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1));
|
||||
return arr.join('');
|
||||
},
|
||||
|
||||
titleize: function(str){
|
||||
return (''+str).replace(/\b./g, function(ch){ return ch.toUpperCase(); });
|
||||
},
|
||||
|
||||
camelize: function(str){
|
||||
return _s.trim(str).replace(/[-_\s]+(.)?/g, function(match, chr){
|
||||
return chr && chr.toUpperCase();
|
||||
});
|
||||
},
|
||||
|
||||
underscored: function(str){
|
||||
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase();
|
||||
},
|
||||
|
||||
dasherize: function(str){
|
||||
return _s.trim(str).replace(/[_\s]+/g, '-').replace(/([A-Z])/g, '-$1').replace(/-+/g, '-').toLowerCase();
|
||||
},
|
||||
|
||||
classify: function(str){
|
||||
str += '';
|
||||
return _s.titleize(str.replace(/_/g, ' ')).replace(/\s/g, '')
|
||||
},
|
||||
|
||||
humanize: function(str){
|
||||
return _s.capitalize(this.underscored(str).replace(/_id$/,'').replace(/_/g, ' '));
|
||||
},
|
||||
|
||||
trim: function(str, characters){
|
||||
str += '';
|
||||
if (!characters && nativeTrim) { return nativeTrim.call(str); }
|
||||
characters = defaultToWhiteSpace(characters);
|
||||
return str.replace(new RegExp('\^' + characters + '+|' + characters + '+$', 'g'), '');
|
||||
},
|
||||
|
||||
ltrim: function(str, characters){
|
||||
str+='';
|
||||
if (!characters && nativeTrimLeft) {
|
||||
return nativeTrimLeft.call(str);
|
||||
}
|
||||
characters = defaultToWhiteSpace(characters);
|
||||
return str.replace(new RegExp('^' + characters + '+'), '');
|
||||
},
|
||||
|
||||
rtrim: function(str, characters){
|
||||
str+='';
|
||||
if (!characters && nativeTrimRight) {
|
||||
return nativeTrimRight.call(str);
|
||||
}
|
||||
characters = defaultToWhiteSpace(characters);
|
||||
return str.replace(new RegExp(characters + '+$'), '');
|
||||
},
|
||||
|
||||
truncate: function(str, length, truncateStr){
|
||||
str += ''; truncateStr = truncateStr || '...';
|
||||
length = ~~length;
|
||||
return str.length > length ? str.slice(0, length) + truncateStr : str;
|
||||
},
|
||||
|
||||
/**
|
||||
* _s.prune: a more elegant version of truncate
|
||||
* prune extra chars, never leaving a half-chopped word.
|
||||
* @author github.com/sergiokas
|
||||
*/
|
||||
prune: function(str, length, pruneStr){
|
||||
str += ''; length = ~~length;
|
||||
pruneStr = pruneStr != null ? ''+pruneStr : '...';
|
||||
|
||||
var pruned, borderChar, template = str.replace(/\W/g, function(ch){
|
||||
return (ch.toUpperCase() !== ch.toLowerCase()) ? 'A' : ' ';
|
||||
});
|
||||
|
||||
borderChar = template.charAt(length);
|
||||
|
||||
pruned = template.slice(0, length);
|
||||
|
||||
// Check if we're in the middle of a word
|
||||
if (borderChar && borderChar.match(/\S/))
|
||||
pruned = pruned.replace(/\s\S+$/, '');
|
||||
|
||||
pruned = _s.rtrim(pruned);
|
||||
|
||||
return (pruned+pruneStr).length > str.length ? str : str.substring(0, pruned.length)+pruneStr;
|
||||
},
|
||||
|
||||
words: function(str, delimiter) {
|
||||
return _s.trim(str, delimiter).split(delimiter || /\s+/);
|
||||
},
|
||||
|
||||
pad: function(str, length, padStr, type) {
|
||||
str += '';
|
||||
|
||||
var padlen = 0;
|
||||
|
||||
length = ~~length;
|
||||
|
||||
if (!padStr) {
|
||||
padStr = ' ';
|
||||
} else if (padStr.length > 1) {
|
||||
padStr = padStr.charAt(0);
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case 'right':
|
||||
padlen = (length - str.length);
|
||||
return str + strRepeat(padStr, padlen);
|
||||
case 'both':
|
||||
padlen = (length - str.length);
|
||||
return strRepeat(padStr, Math.ceil(padlen/2)) +
|
||||
str +
|
||||
strRepeat(padStr, Math.floor(padlen/2));
|
||||
default: // 'left'
|
||||
padlen = (length - str.length);
|
||||
return strRepeat(padStr, padlen) + str;
|
||||
}
|
||||
},
|
||||
|
||||
lpad: function(str, length, padStr) {
|
||||
return _s.pad(str, length, padStr);
|
||||
},
|
||||
|
||||
rpad: function(str, length, padStr) {
|
||||
return _s.pad(str, length, padStr, 'right');
|
||||
},
|
||||
|
||||
lrpad: function(str, length, padStr) {
|
||||
return _s.pad(str, length, padStr, 'both');
|
||||
},
|
||||
|
||||
sprintf: sprintf,
|
||||
|
||||
vsprintf: function(fmt, argv){
|
||||
argv.unshift(fmt);
|
||||
return sprintf.apply(null, argv);
|
||||
},
|
||||
|
||||
toNumber: function(str, decimals) {
|
||||
str += '';
|
||||
var num = parseNumber(parseNumber(str).toFixed(~~decimals));
|
||||
return num === 0 && !str.match(/^0+$/) ? Number.NaN : num;
|
||||
},
|
||||
|
||||
strRight: function(str, sep){
|
||||
str += ''; sep = sep != null ? ''+sep : sep;
|
||||
var pos = !sep ? -1 : str.indexOf(sep);
|
||||
return ~pos ? str.slice(pos+sep.length, str.length) : str;
|
||||
},
|
||||
|
||||
strRightBack: function(str, sep){
|
||||
str += ''; sep = sep != null ? ''+sep : sep;
|
||||
var pos = !sep ? -1 : str.lastIndexOf(sep);
|
||||
return ~pos ? str.slice(pos+sep.length, str.length) : str;
|
||||
},
|
||||
|
||||
strLeft: function(str, sep){
|
||||
str += ''; sep = sep != null ? ''+sep : sep;
|
||||
var pos = !sep ? -1 : str.indexOf(sep);
|
||||
return ~pos ? str.slice(0, pos) : str;
|
||||
},
|
||||
|
||||
strLeftBack: function(str, sep){
|
||||
str += ''; sep = sep != null ? ''+sep : sep;
|
||||
var pos = str.lastIndexOf(sep);
|
||||
return ~pos ? str.slice(0, pos) : str;
|
||||
},
|
||||
|
||||
toSentence: function(array, separator, lastSeparator) {
|
||||
separator || (separator = ', ');
|
||||
lastSeparator || (lastSeparator = ' and ');
|
||||
var length = array.length, str = '';
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
str += array[i];
|
||||
if (i === (length - 2)) { str += lastSeparator; }
|
||||
else if (i < (length - 1)) { str += separator; }
|
||||
}
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
slugify: function(str) {
|
||||
var from = "ąàáäâãćęèéëêìíïîłńòóöôõùúüûñçżź",
|
||||
to = "aaaaaaceeeeeiiiilnooooouuuunczz",
|
||||
regex = new RegExp(defaultToWhiteSpace(from), 'g');
|
||||
|
||||
str = (''+str).toLowerCase();
|
||||
|
||||
str = str.replace(regex, function(ch){
|
||||
var index = from.indexOf(ch);
|
||||
return to.charAt(index) || '-';
|
||||
});
|
||||
|
||||
return _s.trim(str.replace(/[^\w\s-]/g, '').replace(/[-\s]+/g, '-'), '-');
|
||||
},
|
||||
|
||||
exports: function() {
|
||||
var result = {};
|
||||
|
||||
for (var prop in this) {
|
||||
if (!this.hasOwnProperty(prop) || ~_s.words('include contains reverse').indexOf(prop)) continue;
|
||||
result[prop] = this[prop];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
repeat: strRepeat
|
||||
};
|
||||
|
||||
// Aliases
|
||||
|
||||
_s.strip = _s.trim;
|
||||
_s.lstrip = _s.ltrim;
|
||||
_s.rstrip = _s.rtrim;
|
||||
_s.center = _s.lrpad;
|
||||
_s.rjust = _s.lpad;
|
||||
_s.ljust = _s.rpad;
|
||||
_s.contains = _s.include;
|
||||
|
||||
// CommonJS module is defined
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
// Export module
|
||||
module.exports = _s;
|
||||
}
|
||||
exports._s = _s;
|
||||
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
// Register as a named module with AMD.
|
||||
define('underscore.string', function() {
|
||||
return _s;
|
||||
});
|
||||
|
||||
} else {
|
||||
// Integrate with Underscore.js if defined
|
||||
// or create our own underscore object.
|
||||
root._ = root._ || {};
|
||||
root._.string = root._.str = _s;
|
||||
}
|
||||
|
||||
}(this || window));
|
76
node_modules/piler/node_modules/underscore.string/package.json
generated
vendored
Normal file
76
node_modules/piler/node_modules/underscore.string/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
44
node_modules/piler/node_modules/underscore.string/test/run-qunit.js
generated
vendored
Normal file
44
node_modules/piler/node_modules/underscore.string/test/run-qunit.js
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
function waitFor(test, complete, timeout) {
|
||||
var result, start = new Date().getTime()
|
||||
setInterval(function interval() {
|
||||
if ((new Date().getTime() - start < timeout) && !result) {
|
||||
result = test()
|
||||
} else {
|
||||
if (!result) {
|
||||
phantom.exit(1)
|
||||
} else {
|
||||
complete()
|
||||
clearInterval(interval)
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
|
||||
|
||||
var page = new WebPage()
|
||||
|
||||
page.onConsoleMessage = function(msg) {
|
||||
console.log(msg)
|
||||
}
|
||||
|
||||
page.open(phantom.args[0], function(status) {
|
||||
waitFor(function() {
|
||||
return page.evaluate(function(){
|
||||
var el = document.getElementById('qunit-testresult')
|
||||
return el && el.innerText.match('completed')
|
||||
})
|
||||
}, function() {
|
||||
var failures = page.evaluate(function() {
|
||||
var el = document.getElementById('qunit-testresult'),
|
||||
fails = document.getElementsByClassName('fail')
|
||||
|
||||
for (var i = 0; i < fails.length; i++)
|
||||
console.log(fails[i].innerText)
|
||||
|
||||
console.log(el.innerText)
|
||||
|
||||
return parseInt(el.getElementsByClassName('failed')[0].innerHTML)
|
||||
})
|
||||
phantom.exit(failures > 0 ? 1 : 0)
|
||||
}, 10000)
|
||||
})
|
138
node_modules/piler/node_modules/underscore.string/test/speed.js
generated
vendored
Normal file
138
node_modules/piler/node_modules/underscore.string/test/speed.js
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
(function() {
|
||||
|
||||
JSLitmus.test('trimNoNative', function() {
|
||||
return _.trim(" foobar ", " ");
|
||||
});
|
||||
|
||||
JSLitmus.test('trim', function() {
|
||||
return _.trim(" foobar ");
|
||||
});
|
||||
|
||||
JSLitmus.test('trim object-oriented', function() {
|
||||
return _(" foobar ").trim();
|
||||
});
|
||||
|
||||
JSLitmus.test('trim jQuery', function() {
|
||||
return jQuery.trim(" foobar ");
|
||||
});
|
||||
|
||||
JSLitmus.test('ltrimp', function() {
|
||||
return _.ltrim(" foobar ", " ");
|
||||
});
|
||||
|
||||
JSLitmus.test('rtrimp', function() {
|
||||
return _.rtrim(" foobar ", " ");
|
||||
});
|
||||
|
||||
JSLitmus.test('startsWith', function() {
|
||||
return _.startsWith("foobar", "foo");
|
||||
});
|
||||
|
||||
JSLitmus.test('endsWith', function() {
|
||||
return _.endsWith("foobar", "xx");
|
||||
});
|
||||
|
||||
JSLitmus.test('chop', function(){
|
||||
return _('whitespace').chop(2);
|
||||
});
|
||||
|
||||
JSLitmus.test('count', function(){
|
||||
return _('Hello worls').count('l');
|
||||
});
|
||||
|
||||
JSLitmus.test('insert', function() {
|
||||
return _('Hello ').insert(6, 'world');
|
||||
});
|
||||
|
||||
JSLitmus.test('splice', function() {
|
||||
return _('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli');
|
||||
});
|
||||
|
||||
JSLitmus.test('succ', function(){
|
||||
var let = 'a', alphabet = [];
|
||||
|
||||
for (var i=0; i < 26; i++) {
|
||||
alphabet.push(let);
|
||||
let = _(let).succ();
|
||||
}
|
||||
|
||||
return alphabet;
|
||||
});
|
||||
|
||||
JSLitmus.test('titleize', function(){
|
||||
return _('the titleize string method').titleize();
|
||||
});
|
||||
|
||||
JSLitmus.test('truncate', function(){
|
||||
return _('Hello world').truncate(5);
|
||||
});
|
||||
|
||||
JSLitmus.test('prune', function(){
|
||||
return _('Hello world').prune(5);
|
||||
});
|
||||
|
||||
JSLitmus.test('isBlank', function(){
|
||||
return _('').isBlank();
|
||||
});
|
||||
|
||||
JSLitmus.test('escapeHTML', function(){
|
||||
_('<div>Blah blah blah</div>').escapeHTML();
|
||||
});
|
||||
|
||||
JSLitmus.test('unescapeHTML', function(){
|
||||
_('<div>Blah blah blah</div>').unescapeHTML();
|
||||
});
|
||||
|
||||
JSLitmus.test('reverse', function(){
|
||||
_('Hello World').reverse();
|
||||
});
|
||||
|
||||
JSLitmus.test('pad default', function(){
|
||||
_('foo').pad(12);
|
||||
});
|
||||
|
||||
JSLitmus.test('pad hash left', function(){
|
||||
_('foo').pad(12, '#');
|
||||
});
|
||||
|
||||
JSLitmus.test('pad hash right', function(){
|
||||
_('foo').pad(12, '#', 'right');
|
||||
});
|
||||
|
||||
JSLitmus.test('pad hash both', function(){
|
||||
_('foo').pad(12, '#', 'both');
|
||||
});
|
||||
|
||||
JSLitmus.test('pad hash both longPad', function(){
|
||||
_('foo').pad(12, 'f00f00f00', 'both');
|
||||
});
|
||||
|
||||
JSLitmus.test('toNumber', function(){
|
||||
_('10.232323').toNumber(2);
|
||||
});
|
||||
|
||||
JSLitmus.test('strRight', function(){
|
||||
_('aaa_bbb_ccc').strRight('_');
|
||||
});
|
||||
|
||||
JSLitmus.test('strRightBack', function(){
|
||||
_('aaa_bbb_ccc').strRightBack('_');
|
||||
});
|
||||
|
||||
JSLitmus.test('strLeft', function(){
|
||||
_('aaa_bbb_ccc').strLeft('_');
|
||||
});
|
||||
|
||||
JSLitmus.test('strLeftBack', function(){
|
||||
_('aaa_bbb_ccc').strLeftBack('_');
|
||||
});
|
||||
|
||||
JSLitmus.test('join', function(){
|
||||
_('separator').join(1, 2, 3, 4, 5, 6, 7, 8, 'foo', 'bar', 'lol', 'wut');
|
||||
});
|
||||
|
||||
JSLitmus.test('slugify', function(){
|
||||
_("Un éléphant à l'orée du bois").slugify();
|
||||
});
|
||||
|
||||
})();
|
438
node_modules/piler/node_modules/underscore.string/test/strings.js
generated
vendored
Normal file
438
node_modules/piler/node_modules/underscore.string/test/strings.js
generated
vendored
Normal file
@ -0,0 +1,438 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
// Include Underscore.string methods to Underscore namespace
|
||||
_.mixin(_.str.exports());
|
||||
|
||||
module("String extensions");
|
||||
|
||||
test("Strings: trim", function() {
|
||||
equals(_.trim(123), "123", "Non string");
|
||||
equals(_(" foo").trim(), "foo");
|
||||
equals(_("foo ").trim(), "foo");
|
||||
equals(_(" foo ").trim(), "foo");
|
||||
equals(_(" foo ").trim(), "foo");
|
||||
equals(_(" foo ", " ").trim(), "foo", "Manually set whitespace");
|
||||
|
||||
equals(_("ffoo").trim("f"), "oo");
|
||||
equals(_("ooff").trim("f"), "oo");
|
||||
equals(_("ffooff").trim("f"), "oo");
|
||||
|
||||
|
||||
equals(_("_-foobar-_").trim("_-"), "foobar");
|
||||
|
||||
equals(_("http://foo/").trim("/"), "http://foo");
|
||||
equals(_("c:\\").trim('\\'), "c:");
|
||||
|
||||
equals(_(123).trim(), '123');
|
||||
equals(_(123).trim(3), '12');
|
||||
});
|
||||
|
||||
test("Strings: ltrim", function() {
|
||||
equals(_(" foo").ltrim(), "foo");
|
||||
equals(_(" foo").ltrim(), "foo");
|
||||
equals(_("foo ").ltrim(), "foo ");
|
||||
equals(_(" foo ").ltrim(), "foo ");
|
||||
|
||||
|
||||
equals(_("ffoo").ltrim("f"), "oo");
|
||||
equals(_("ooff").ltrim("f"), "ooff");
|
||||
equals(_("ffooff").ltrim("f"), "ooff");
|
||||
|
||||
equals(_("_-foobar-_").ltrim("_-"), "foobar-_");
|
||||
|
||||
equals(_(123).ltrim(1), '23');
|
||||
});
|
||||
|
||||
test("Strings: rtrim", function() {
|
||||
equals(_("http://foo/").rtrim("/"), "http://foo", 'clean trailing slash');
|
||||
equals(_(" foo").rtrim(), " foo");
|
||||
equals(_("foo ").rtrim(), "foo");
|
||||
equals(_("foo ").rtrim(), "foo");
|
||||
equals(_("foo bar ").rtrim(), "foo bar");
|
||||
equals(_(" foo ").rtrim(), " foo");
|
||||
|
||||
equals(_("ffoo").rtrim("f"), "ffoo");
|
||||
equals(_("ooff").rtrim("f"), "oo");
|
||||
equals(_("ffooff").rtrim("f"), "ffoo");
|
||||
|
||||
equals(_("_-foobar-_").rtrim("_-"), "_-foobar");
|
||||
|
||||
equals(_(123).rtrim(3), '12');
|
||||
});
|
||||
|
||||
test("Strings: capitalize", function() {
|
||||
equals(_("fabio").capitalize(), "Fabio", 'First letter is upper case');
|
||||
equals(_.capitalize("fabio"), "Fabio", 'First letter is upper case');
|
||||
equals(_.capitalize('FOO'), 'FOO', 'Other letters unchanged');
|
||||
equals(_(123).capitalize(), "123", "Non string");
|
||||
});
|
||||
|
||||
test("Strings: join", function() {
|
||||
equals(_.join("", "foo", "bar"), "foobar", 'basic join');
|
||||
equals(_.join("", 1, "foo", 2), "1foo2", 'join numbers and strings');
|
||||
equals(_.join(" ","foo", "bar"), "foo bar", 'join with spaces');
|
||||
equals(_.join("1", "2", "2"), "212", 'join number strings');
|
||||
equals(_.join(1, 2, 2), "212", 'join numbers');
|
||||
equals(_(" ").join("foo", "bar"), "foo bar", 'join object oriented');
|
||||
});
|
||||
|
||||
test("Strings: reverse", function() {
|
||||
equals(_.str.reverse("foo"), "oof" );
|
||||
equals(_.str.reverse("foobar"), "raboof" );
|
||||
equals(_.str.reverse("foo bar"), "rab oof" );
|
||||
equals(_.str.reverse("saippuakauppias"), "saippuakauppias" );
|
||||
equals(_.str.reverse(123), "321", "Non string");
|
||||
equals(_.str.reverse(123.45), "54.321", "Non string");
|
||||
});
|
||||
|
||||
test("Strings: clean", function() {
|
||||
equals(_(" foo bar ").clean(), "foo bar");
|
||||
equals(_(123).clean(), "123");
|
||||
});
|
||||
|
||||
test("Strings: sprintf", function() {
|
||||
// Should be very tested function already. Thanks to
|
||||
// http://www.diveintojavascript.com/projects/sprintf-for-javascript
|
||||
equals(_.sprintf("Hello %s", "me"), "Hello me", 'basic');
|
||||
equals(_("Hello %s").sprintf("me"), "Hello me", 'object');
|
||||
equals(_("hello %s").chain().sprintf("me").capitalize().value(), "Hello me", 'Chaining works');
|
||||
equals(_.sprintf("%.1f", 1.22222), "1.2", 'round');
|
||||
equals(_.sprintf("%.1f", 1.17), "1.2", 'round 2');
|
||||
equals(_.sprintf("%(id)d - %(name)s", {id: 824, name: "Hello World"}), "824 - Hello World", 'Named replacements work');
|
||||
equals(_.sprintf("%(args[0].id)d - %(args[1].name)s", {args: [{id: 824}, {name: "Hello World"}]}), "824 - Hello World", 'Named replacements with arrays work');
|
||||
});
|
||||
|
||||
|
||||
test("Strings: vsprintf", function() {
|
||||
equals(_.vsprintf("Hello %s", ["me"]), "Hello me", 'basic');
|
||||
equals(_("Hello %s").vsprintf(["me"]), "Hello me", 'object');
|
||||
equals(_("hello %s").chain().vsprintf(["me"]).capitalize().value(), "Hello me", 'Chaining works');
|
||||
equals(_.vsprintf("%.1f", [1.22222]), "1.2", 'round');
|
||||
equals(_.vsprintf("%.1f", [1.17]), "1.2", 'round 2');
|
||||
equals(_.vsprintf("%(id)d - %(name)s", [{id: 824, name: "Hello World"}]), "824 - Hello World", 'Named replacement works');
|
||||
equals(_.vsprintf("%(args[0].id)d - %(args[1].name)s", [{args: [{id: 824}, {name: "Hello World"}]}]), "824 - Hello World", 'Named replacement with arrays works');
|
||||
});
|
||||
|
||||
test("Strings: startsWith", function() {
|
||||
ok(_("foobar").startsWith("foo"), 'foobar starts with foo');
|
||||
ok(!_("oobar").startsWith("foo"), 'oobar does not start with foo');
|
||||
ok(_(12345).startsWith(123), '12345 starts with 123');
|
||||
ok(!_(2345).startsWith(123), '2345 does not start with 123');
|
||||
});
|
||||
|
||||
test("Strings: endsWith", function() {
|
||||
ok(_("foobar").endsWith("bar"), 'foobar ends with bar');
|
||||
ok(_.endsWith("foobar", "bar"), 'foobar ends with bar');
|
||||
ok(_.endsWith("00018-0000062.Plone.sdh264.1a7264e6912a91aa4a81b64dc5517df7b8875994.mp4", "mp4"), 'endsWith .mp4');
|
||||
ok(!_("fooba").endsWith("bar"), 'fooba does not end with bar');
|
||||
ok(_.endsWith(12345, 45), '12345 ends with 45');
|
||||
ok(!_.endsWith(12345, 6), '12345 does not end with 6');
|
||||
});
|
||||
|
||||
test("Strings: include", function() {
|
||||
ok(_.str.include("foobar", "bar"), 'foobar includes bar');
|
||||
ok(!_.str.include("foobar", "buzz"), 'foobar does not includes buzz');
|
||||
ok(_.str.include(12345, 34), '12345 includes 34');
|
||||
ok(!_.str.contains(12345, 6), '12345 does not includes 6');
|
||||
});
|
||||
|
||||
test('String: chop', function(){
|
||||
ok(_('whitespace').chop(2).length === 5, "output ['wh','it','es','pa','ce']");
|
||||
ok(_('whitespace').chop(3).length === 4, "output ['whi','tes','pac','e']");
|
||||
ok(_('whitespace').chop()[0].length === 10, "output ['whitespace']");
|
||||
ok(_(12345).chop(1).length === 5, "output ['1','2','3','4','5']");
|
||||
});
|
||||
|
||||
test('String: clean', function(){
|
||||
equals(_.clean(' foo bar '), 'foo bar');
|
||||
equals(_.clean(1), '1');
|
||||
});
|
||||
|
||||
test('String: count', function(){
|
||||
equals(_('Hello world').count('l'), 3);
|
||||
equals(_('Hello world').count('Hello'), 1);
|
||||
equals(_('Hello world').count('foo'), 0);
|
||||
equals(_('x.xx....x.x').count('x'), 5);
|
||||
equals(_(12345).count(1), 1);
|
||||
equals(_(11345).count(1), 2);
|
||||
});
|
||||
|
||||
test('String: insert', function(){
|
||||
equals(_('Hello ').insert(6, 'Jessy'), 'Hello Jessy');
|
||||
equals(_('Hello ').insert(100, 'Jessy'), 'Hello Jessy');
|
||||
equals(_(12345).insert(6, 'Jessy'), '12345Jessy');
|
||||
});
|
||||
|
||||
test('String: splice', function(){
|
||||
equals(_('https://edtsech@bitbucket.org/edtsech/underscore.strings').splice(30, 7, 'epeli'),
|
||||
'https://edtsech@bitbucket.org/epeli/underscore.strings');
|
||||
equals(_.splice(12345, 1, 2, 321), '132145', 'Non strings');
|
||||
});
|
||||
|
||||
test('String: succ', function(){
|
||||
equals(_('a').succ(), 'b');
|
||||
equals(_('A').succ(), 'B');
|
||||
equals(_('+').succ(), ',');
|
||||
equals(_(1).succ(), '2');
|
||||
});
|
||||
|
||||
test('String: titleize', function(){
|
||||
equals(_('the titleize string method').titleize(), 'The Titleize String Method');
|
||||
equals(_('the titleize string method').titleize(), 'The Titleize String Method');
|
||||
equals(_(123).titleize(), '123');
|
||||
});
|
||||
|
||||
test('String: camelize', function(){
|
||||
equals(_('the_camelize_string_method').camelize(), 'theCamelizeStringMethod');
|
||||
equals(_('-the-camelize-string-method').camelize(), 'TheCamelizeStringMethod');
|
||||
equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod');
|
||||
equals(_(' the camelize string method').camelize(), 'theCamelizeStringMethod');
|
||||
equals(_('the camelize string method').camelize(), 'theCamelizeStringMethod');
|
||||
equals(_(123).camelize(), '123');
|
||||
});
|
||||
|
||||
test('String: underscored', function(){
|
||||
equals(_('the-underscored-string-method').underscored(), 'the_underscored_string_method');
|
||||
equals(_('theUnderscoredStringMethod').underscored(), 'the_underscored_string_method');
|
||||
equals(_('TheUnderscoredStringMethod').underscored(), 'the_underscored_string_method');
|
||||
equals(_(' the underscored string method').underscored(), 'the_underscored_string_method');
|
||||
equals(_(123).underscored(), '123');
|
||||
});
|
||||
|
||||
test('String: dasherize', function(){
|
||||
equals(_('the_dasherize_string_method').dasherize(), 'the-dasherize-string-method');
|
||||
equals(_('TheDasherizeStringMethod').dasherize(), '-the-dasherize-string-method');
|
||||
equals(_('thisIsATest').dasherize(), 'this-is-a-test');
|
||||
equals(_('this Is A Test').dasherize(), 'this-is-a-test');
|
||||
equals(_('thisIsATest123').dasherize(), 'this-is-a-test123');
|
||||
equals(_('123thisIsATest').dasherize(), '123this-is-a-test');
|
||||
equals(_('the dasherize string method').dasherize(), 'the-dasherize-string-method');
|
||||
equals(_('the dasherize string method ').dasherize(), 'the-dasherize-string-method');
|
||||
equals(_('téléphone').dasherize(), 'téléphone');
|
||||
equals(_('foo$bar').dasherize(), 'foo$bar');
|
||||
equals(_(123).dasherize(), '123');
|
||||
});
|
||||
|
||||
test('String: camelize', function(){
|
||||
equals(_.camelize('-moz-transform'), 'MozTransform');
|
||||
equals(_.camelize('webkit-transform'), 'webkitTransform');
|
||||
equals(_.camelize('under_scored'), 'underScored');
|
||||
equals(_.camelize(' with spaces'), 'withSpaces');
|
||||
});
|
||||
|
||||
test('String: join', function(){
|
||||
equals(_.join(1, 2, 3, 4), '21314');
|
||||
equals(_.join('|', 'foo', 'bar', 'baz'), 'foo|bar|baz');
|
||||
});
|
||||
|
||||
test('String: classify', function(){
|
||||
equals(_.classify(1), '1');
|
||||
equals(_('some_class_name').classify(), 'SomeClassName');
|
||||
});
|
||||
|
||||
test('String: humanize', function(){
|
||||
equals(_('the_humanize_string_method').humanize(), 'The humanize string method');
|
||||
equals(_('ThehumanizeStringMethod').humanize(), 'Thehumanize string method');
|
||||
equals(_('the humanize string method').humanize(), 'The humanize string method');
|
||||
equals(_('the humanize_id string method_id').humanize(), 'The humanize id string method');
|
||||
equals(_('the humanize string method ').humanize(), 'The humanize string method');
|
||||
equals(_(' capitalize dash-CamelCase_underscore trim ').humanize(), 'Capitalize dash camel case underscore trim');
|
||||
equals(_(123).humanize(), '123');
|
||||
});
|
||||
|
||||
test('String: truncate', function(){
|
||||
equals(_('Hello world').truncate(6, 'read more'), 'Hello read more');
|
||||
equals(_('Hello world').truncate(5), 'Hello...');
|
||||
equals(_('Hello').truncate(10), 'Hello');
|
||||
equals(_(1234567890).truncate(5), '12345...');
|
||||
});
|
||||
|
||||
test('String: prune', function(){
|
||||
equals(_('Hello, cruel world').prune(6, ' read more'), 'Hello read more');
|
||||
equals(_('Hello, world').prune(5, 'read a lot more'), 'Hello, world');
|
||||
equals(_('Hello, world').prune(5), 'Hello...');
|
||||
equals(_('Hello, world').prune(8), 'Hello...');
|
||||
equals(_('Hello, cruel world').prune(15), 'Hello, cruel...');
|
||||
equals(_('Hello world').prune(22), 'Hello world');
|
||||
equals(_('Привет, жестокий мир').prune(6, ' read more'), 'Привет read more');
|
||||
equals(_('Привет, мир').prune(6, 'read a lot more'), 'Привет, мир');
|
||||
equals(_('Привет, мир').prune(6), 'Привет...');
|
||||
equals(_('Привет, мир').prune(8), 'Привет...');
|
||||
equals(_('Привет, жестокий мир').prune(16), 'Привет, жестокий...');
|
||||
equals(_('Привет, мир').prune(22), 'Привет, мир');
|
||||
equals(_(123).prune(10), '123');
|
||||
equals(_(123).prune(1,1), '11');
|
||||
});
|
||||
|
||||
test('String: isBlank', function(){
|
||||
ok(_('').isBlank());
|
||||
ok(_(' ').isBlank());
|
||||
ok(_('\n').isBlank());
|
||||
ok(!_('a').isBlank());
|
||||
ok(!_('0').isBlank());
|
||||
ok(!_(0).isBlank());
|
||||
});
|
||||
|
||||
test('String: escapeHTML', function(){
|
||||
equals(_('<div>Blah & "blah" & \'blah\'</div>').escapeHTML(),
|
||||
'<div>Blah & "blah" & 'blah'</div>');
|
||||
equals(_('<').escapeHTML(), '&lt;');
|
||||
equals(_(5).escapeHTML(), '5');
|
||||
// equals(_(undefined).escapeHTML(), '');
|
||||
});
|
||||
|
||||
test('String: unescapeHTML', function(){
|
||||
equals(_('<div>Blah & "blah" & 'blah'</div>').unescapeHTML(),
|
||||
'<div>Blah & "blah" & \'blah\'</div>');
|
||||
equals(_('&lt;').unescapeHTML(), '<');
|
||||
equals(_(''').unescapeHTML(), "'");
|
||||
equals(_(''').unescapeHTML(), "'");
|
||||
equals(_('J').unescapeHTML(), "J");
|
||||
equals(_('J').unescapeHTML(), "J");
|
||||
equals(_('J').unescapeHTML(), "J");
|
||||
equals(_('&_#39;').unescapeHTML(), "&_#39;");
|
||||
equals(_(''_;').unescapeHTML(), "'_;");
|
||||
equals(_('&#38;').unescapeHTML(), "&");
|
||||
equals(_('&amp;').unescapeHTML(), "&");
|
||||
equals(_(5).unescapeHTML(), '5');
|
||||
// equals(_(undefined).unescapeHTML(), '');
|
||||
});
|
||||
|
||||
test('String: words', function() {
|
||||
equals(_("I love you!").words().length, 3);
|
||||
equals(_(" I love you! ").words().length, 3);
|
||||
equals(_("I_love_you!").words('_').length, 3);
|
||||
equals(_("I-love-you!").words(/-/).length, 3);
|
||||
equals(_(123).words().length, 1);
|
||||
});
|
||||
|
||||
test('String: chars', function() {
|
||||
equals(_("Hello").chars().length, 5);
|
||||
equals(_(123).chars().length, 3);
|
||||
});
|
||||
|
||||
test('String: lines', function() {
|
||||
equals(_("Hello\nWorld").lines().length, 2);
|
||||
equals(_("Hello World").lines().length, 1);
|
||||
equals(_(123).lines().length, 1);
|
||||
});
|
||||
|
||||
test('String: pad', function() {
|
||||
equals(_("1").pad(8), ' 1');
|
||||
equals(_(1).pad(8), ' 1');
|
||||
equals(_("1").pad(8, '0'), '00000001');
|
||||
equals(_("1").pad(8, '0', 'left'), '00000001');
|
||||
equals(_("1").pad(8, '0', 'right'), '10000000');
|
||||
equals(_("1").pad(8, '0', 'both'), '00001000');
|
||||
equals(_("foo").pad(8, '0', 'both'), '000foo00');
|
||||
equals(_("foo").pad(7, '0', 'both'), '00foo00');
|
||||
equals(_("foo").pad(7, '!@$%dofjrofj', 'both'), '!!foo!!');
|
||||
});
|
||||
|
||||
test('String: lpad', function() {
|
||||
equals(_("1").lpad(8), ' 1');
|
||||
equals(_(1).lpad(8), ' 1');
|
||||
equals(_("1").lpad(8, '0'), '00000001');
|
||||
equals(_("1").lpad(8, '0', 'left'), '00000001');
|
||||
});
|
||||
|
||||
test('String: rpad', function() {
|
||||
equals(_("1").rpad(8), '1 ');
|
||||
equals(_(1).lpad(8), ' 1');
|
||||
equals(_("1").rpad(8, '0'), '10000000');
|
||||
equals(_("foo").rpad(8, '0'), 'foo00000');
|
||||
equals(_("foo").rpad(7, '0'), 'foo0000');
|
||||
});
|
||||
|
||||
test('String: lrpad', function() {
|
||||
equals(_("1").lrpad(8), ' 1 ');
|
||||
equals(_(1).lrpad(8), ' 1 ');
|
||||
equals(_("1").lrpad(8, '0'), '00001000');
|
||||
equals(_("foo").lrpad(8, '0'), '000foo00');
|
||||
equals(_("foo").lrpad(7, '0'), '00foo00');
|
||||
equals(_("foo").lrpad(7, '!@$%dofjrofj'), '!!foo!!');
|
||||
});
|
||||
|
||||
test('String: toNumber', function() {
|
||||
deepEqual(_("not a number").toNumber(), Number.NaN);
|
||||
equals(_(0).toNumber(), 0);
|
||||
equals(_("0").toNumber(), 0);
|
||||
equals(_("0000").toNumber(), 0);
|
||||
equals(_("2.345").toNumber(), 2);
|
||||
equals(_("2.345").toNumber(NaN), 2);
|
||||
equals(_("2.345").toNumber(2), 2.35);
|
||||
equals(_("2.344").toNumber(2), 2.34);
|
||||
equals(_("2").toNumber(2), 2.00);
|
||||
equals(_(2).toNumber(2), 2.00);
|
||||
equals(_(-2).toNumber(), -2);
|
||||
equals(_("-2").toNumber(), -2);
|
||||
});
|
||||
|
||||
test('String: strRight', function() {
|
||||
equals(_("This_is_a_test_string").strRight("_"), "is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strRight("string"), "");
|
||||
equals(_("This_is_a_test_string").strRight(), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strRight(""), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strRight("-"), "This_is_a_test_string");
|
||||
equals(_(12345).strRight(2), "345");
|
||||
});
|
||||
|
||||
test('String: strRightBack', function() {
|
||||
equals(_("This_is_a_test_string").strRightBack("_"), "string");
|
||||
equals(_("This_is_a_test_string").strRightBack("string"), "");
|
||||
equals(_("This_is_a_test_string").strRightBack(), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strRightBack(""), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strRightBack("-"), "This_is_a_test_string");
|
||||
equals(_(12345).strRightBack(2), "345");
|
||||
});
|
||||
|
||||
test('String: strLeft', function() {
|
||||
equals(_("This_is_a_test_string").strLeft("_"), "This");
|
||||
equals(_("This_is_a_test_string").strLeft("This"), "");
|
||||
equals(_("This_is_a_test_string").strLeft(), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strLeft(""), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strLeft("-"), "This_is_a_test_string");
|
||||
equals(_(123454321).strLeft(3), "12");
|
||||
});
|
||||
|
||||
test('String: strLeftBack', function() {
|
||||
equals(_("This_is_a_test_string").strLeftBack("_"), "This_is_a_test");
|
||||
equals(_("This_is_a_test_string").strLeftBack("This"), "");
|
||||
equals(_("This_is_a_test_string").strLeftBack(), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strLeftBack(""), "This_is_a_test_string");
|
||||
equals(_("This_is_a_test_string").strLeftBack("-"), "This_is_a_test_string");
|
||||
equals(_(123454321).strLeftBack(3), "123454");
|
||||
});
|
||||
|
||||
test('Strings: stripTags', function() {
|
||||
equals(_('a <a href="#">link</a>').stripTags(), 'a link');
|
||||
equals(_('a <a href="#">link</a><script>alert("hello world!")</scr'+'ipt>').stripTags(), 'a linkalert("hello world!")');
|
||||
equals(_('<html><body>hello world</body></html>').stripTags(), 'hello world');
|
||||
equals(_(123).stripTags(), '123');
|
||||
});
|
||||
|
||||
test('Strings: toSentence', function() {
|
||||
equals(_.toSentence(['jQuery']), 'jQuery', 'array with a single element');
|
||||
equals(_.toSentence(['jQuery', 'MooTools']), 'jQuery and MooTools', 'array with two elements');
|
||||
equals(_.toSentence(['jQuery', 'MooTools', 'Prototype']), 'jQuery, MooTools and Prototype', 'array with three elements');
|
||||
equals(_.toSentence(['jQuery', 'MooTools', 'Prototype', 'YUI']), 'jQuery, MooTools, Prototype and YUI', 'array with multiple elements');
|
||||
equals(_.toSentence(['jQuery', 'MooTools', 'Prototype'], ',', ' or '), 'jQuery,MooTools or Prototype', 'handles custom separators');
|
||||
});
|
||||
|
||||
test('Strings: slugify', function() {
|
||||
equals(_("Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/").slugify(), "jack-jill-like-numbers-123-and-4-and-silly-characters");
|
||||
equals(_("Un éléphant à l'orée du bois").slugify(), "un-elephant-a-loree-du-bois");
|
||||
equals(_("I know latin characters: á í ó ú ç ã õ ñ ü").slugify(), "i-know-latin-characters-a-i-o-u-c-a-o-n-u");
|
||||
equals(_("I am a word too, even though I am but a single letter: i!").slugify(), "i-am-a-word-too-even-though-i-am-but-a-single-letter-i");
|
||||
});
|
||||
|
||||
test('Strings: repeat', function() {
|
||||
equals(_.repeat('foo'), '');
|
||||
equals(_.repeat('foo', 3), 'foofoofoo');
|
||||
equals(_.repeat('foo', '3'), 'foofoofoo');
|
||||
equals(_.repeat(123, 2), '123123');
|
||||
equals(_.repeat(1234, 2, '*'), '1234*1234');
|
||||
equals(_.repeat(1234, 2, 5), '123451234');
|
||||
});
|
||||
|
||||
});
|
12
node_modules/piler/node_modules/underscore.string/test/strings_standalone.js
generated
vendored
Normal file
12
node_modules/piler/node_modules/underscore.string/test/strings_standalone.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("String extensions");
|
||||
|
||||
test("underscore not included", function() {
|
||||
raises(function() { _("foo") }, /TypeError/);
|
||||
});
|
||||
|
||||
test("provides standalone functions", function() {
|
||||
equals(typeof _.str.trim, "function");
|
||||
});
|
||||
});
|
31
node_modules/piler/node_modules/underscore.string/test/test.html
generated
vendored
Normal file
31
node_modules/piler/node_modules/underscore.string/test/test.html
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Underscore.strings Test Suite</title>
|
||||
<link rel="stylesheet" href="test_underscore/vendor/qunit.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="test_underscore/vendor/jquery.js"></script>
|
||||
<script type="text/javascript" src="test_underscore/vendor/qunit.js"></script>
|
||||
<script type="text/javascript" src="test_underscore/vendor/jslitmus.js"></script>
|
||||
<script type="text/javascript" src="underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="strings.js"></script>
|
||||
<script type="text/javascript" src="speed.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Underscore.string Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<br />
|
||||
<h1 class="qunit-header">Underscore.string Speed Suite</h1>
|
||||
<!-- <h2 class="qunit-userAgent">
|
||||
A representative sample of the functions are benchmarked here, to provide
|
||||
a sense of how fast they might run in different browsers.
|
||||
Each iteration runs on an array of 1000 elements.<br /><br />
|
||||
For example, the 'intersect' test measures the number of times you can
|
||||
find the intersection of two thousand-element arrays in one second.
|
||||
</h2> -->
|
||||
<br />
|
||||
</body>
|
||||
</html>
|
18
node_modules/piler/node_modules/underscore.string/test/test_standalone.html
generated
vendored
Normal file
18
node_modules/piler/node_modules/underscore.string/test/test_standalone.html
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Underscore.strings Test Suite</title>
|
||||
<link rel="stylesheet" href="test_underscore/vendor/qunit.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="test_underscore/vendor/jquery.js"></script>
|
||||
<script type="text/javascript" src="test_underscore/vendor/qunit.js"></script>
|
||||
<script type="text/javascript" src="../lib/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="strings_standalone.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Underscore.string Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
</body>
|
||||
</html>
|
166
node_modules/piler/node_modules/underscore.string/test/test_underscore/arrays.js
generated
vendored
Normal file
166
node_modules/piler/node_modules/underscore.string/test/test_underscore/arrays.js
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Arrays");
|
||||
|
||||
test("arrays: first", function() {
|
||||
equals(_.first([1,2,3]), 1, 'can pull out the first element of an array');
|
||||
equals(_([1, 2, 3]).first(), 1, 'can perform OO-style "first()"');
|
||||
equals(_.first([1,2,3], 0).join(', '), "", 'can pass an index to first');
|
||||
equals(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');
|
||||
equals(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first');
|
||||
var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);
|
||||
equals(result, 4, 'works on an arguments object.');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.first);
|
||||
equals(result.join(','), '1,1', 'works well with _.map');
|
||||
});
|
||||
|
||||
test("arrays: rest", function() {
|
||||
var numbers = [1, 2, 3, 4];
|
||||
equals(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
|
||||
equals(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
|
||||
equals(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');
|
||||
var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);
|
||||
equals(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.rest);
|
||||
equals(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');
|
||||
});
|
||||
|
||||
test("arrays: initial", function() {
|
||||
equals(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()');
|
||||
equals(_.initial([1,2,3,4],2).join(", "), "1, 2", 'initial can take an index');
|
||||
var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4);
|
||||
equals(result.join(", "), "1, 2, 3", 'initial works on arguments object');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.initial);
|
||||
equals(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');
|
||||
});
|
||||
|
||||
test("arrays: last", function() {
|
||||
equals(_.last([1,2,3]), 3, 'can pull out the last element of an array');
|
||||
equals(_.last([1,2,3], 0).join(', '), "", 'can pass an index to last');
|
||||
equals(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last');
|
||||
equals(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last');
|
||||
var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4);
|
||||
equals(result, 4, 'works on an arguments object');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.last);
|
||||
equals(result.join(','), '3,3', 'works well with _.map');
|
||||
});
|
||||
|
||||
test("arrays: compact", function() {
|
||||
equals(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
|
||||
var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3);
|
||||
equals(result, 3, 'works on an arguments object');
|
||||
});
|
||||
|
||||
test("arrays: flatten", function() {
|
||||
if (window.JSON) {
|
||||
var list = [1, [2], [3, [[[4]]]]];
|
||||
equals(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays');
|
||||
equals(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays');
|
||||
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
|
||||
equals(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object');
|
||||
}
|
||||
});
|
||||
|
||||
test("arrays: without", function() {
|
||||
var list = [1, 2, 1, 0, 3, 1, 4];
|
||||
equals(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');
|
||||
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
|
||||
equals(result.join(', '), '2, 3, 4', 'works on an arguments object');
|
||||
|
||||
var list = [{one : 1}, {two : 2}];
|
||||
ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');
|
||||
ok(_.without(list, list[0]).length == 1, 'ditto.');
|
||||
});
|
||||
|
||||
test("arrays: uniq", function() {
|
||||
var list = [1, 2, 1, 3, 1, 4];
|
||||
equals(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');
|
||||
|
||||
var list = [1, 1, 1, 2, 2, 3];
|
||||
equals(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');
|
||||
|
||||
var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];
|
||||
var iterator = function(value) { return value.name; };
|
||||
equals(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
|
||||
|
||||
var iterator = function(value) { return value +1; };
|
||||
var list = [1, 2, 2, 3, 4, 4];
|
||||
equals(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
|
||||
|
||||
var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);
|
||||
equals(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
|
||||
});
|
||||
|
||||
test("arrays: intersection", function() {
|
||||
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
||||
equals(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
|
||||
equals(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
|
||||
var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');
|
||||
equals(result.join(''), 'moe', 'works on an arguments object');
|
||||
});
|
||||
|
||||
test("arrays: union", function() {
|
||||
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
|
||||
equals(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
|
||||
|
||||
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);
|
||||
equals(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
|
||||
});
|
||||
|
||||
test("arrays: difference", function() {
|
||||
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
||||
equals(result.join(' '), '1 3', 'takes the difference of two arrays');
|
||||
|
||||
var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);
|
||||
equals(result.join(' '), '3 4', 'takes the difference of three arrays');
|
||||
});
|
||||
|
||||
test('arrays: zip', function() {
|
||||
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
||||
var stooges = _.zip(names, ages, leaders);
|
||||
equals(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
|
||||
});
|
||||
|
||||
test("arrays: indexOf", function() {
|
||||
var numbers = [1, 2, 3];
|
||||
numbers.indexOf = null;
|
||||
equals(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
||||
var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);
|
||||
equals(result, 1, 'works on an arguments object');
|
||||
equals(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
|
||||
var numbers = [10, 20, 30, 40, 50], num = 35;
|
||||
var index = _.indexOf(numbers, num, true);
|
||||
equals(index, -1, '35 is not in the list');
|
||||
|
||||
numbers = [10, 20, 30, 40, 50]; num = 40;
|
||||
index = _.indexOf(numbers, num, true);
|
||||
equals(index, 3, '40 is in the list');
|
||||
|
||||
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
||||
index = _.indexOf(numbers, num, true);
|
||||
equals(index, 1, '40 is in the list');
|
||||
});
|
||||
|
||||
test("arrays: lastIndexOf", function() {
|
||||
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||
numbers.lastIndexOf = null;
|
||||
equals(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
equals(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
|
||||
equals(result, 5, 'works on an arguments object');
|
||||
equals(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
});
|
||||
|
||||
test("arrays: range", function() {
|
||||
equals(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');
|
||||
equals(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
|
||||
equals(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
||||
equals(_.range(8, 5).join(''), '', 'range with two arguments a & b, b<a generates an empty array');
|
||||
equals(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c');
|
||||
equals(_.range(3, 10, 15).join(''), '3', 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a');
|
||||
equals(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
|
||||
equals(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs');
|
||||
});
|
||||
|
||||
});
|
59
node_modules/piler/node_modules/underscore.string/test/test_underscore/chaining.js
generated
vendored
Normal file
59
node_modules/piler/node_modules/underscore.string/test/test_underscore/chaining.js
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Chaining");
|
||||
|
||||
test("chaining: map/flatten/reduce", function() {
|
||||
var lyrics = [
|
||||
"I'm a lumberjack and I'm okay",
|
||||
"I sleep all night and I work all day",
|
||||
"He's a lumberjack and he's okay",
|
||||
"He sleeps all night and he works all day"
|
||||
];
|
||||
var counts = _(lyrics).chain()
|
||||
.map(function(line) { return line.split(''); })
|
||||
.flatten()
|
||||
.reduce(function(hash, l) {
|
||||
hash[l] = hash[l] || 0;
|
||||
hash[l]++;
|
||||
return hash;
|
||||
}, {}).value();
|
||||
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
|
||||
});
|
||||
|
||||
test("chaining: select/reject/sortBy", function() {
|
||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||
numbers = _(numbers).chain().select(function(n) {
|
||||
return n % 2 == 0;
|
||||
}).reject(function(n) {
|
||||
return n % 4 == 0;
|
||||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).value();
|
||||
equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
||||
});
|
||||
|
||||
test("chaining: select/reject/sortBy in functional style", function() {
|
||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||
numbers = _.chain(numbers).select(function(n) {
|
||||
return n % 2 == 0;
|
||||
}).reject(function(n) {
|
||||
return n % 4 == 0;
|
||||
}).sortBy(function(n) {
|
||||
return -n;
|
||||
}).value();
|
||||
equals(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
||||
});
|
||||
|
||||
test("chaining: reverse/concat/unshift/pop/map", function() {
|
||||
var numbers = [1,2,3,4,5];
|
||||
numbers = _(numbers).chain()
|
||||
.reverse()
|
||||
.concat([5, 5, 5])
|
||||
.unshift(17)
|
||||
.pop()
|
||||
.map(function(n){ return n * 2; })
|
||||
.value();
|
||||
equals(numbers.join(', '), "34, 10, 8, 6, 4, 2, 10, 10", 'can chain together array functions.');
|
||||
});
|
||||
|
||||
});
|
270
node_modules/piler/node_modules/underscore.string/test/test_underscore/collections.js
generated
vendored
Normal file
270
node_modules/piler/node_modules/underscore.string/test/test_underscore/collections.js
generated
vendored
Normal file
@ -0,0 +1,270 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Collections");
|
||||
|
||||
test("collections: each", function() {
|
||||
_.each([1, 2, 3], function(num, i) {
|
||||
equals(num, i + 1, 'each iterators provide value and iteration count');
|
||||
});
|
||||
|
||||
var answers = [];
|
||||
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});
|
||||
equals(answers.join(', '), '5, 10, 15', 'context object property accessed');
|
||||
|
||||
answers = [];
|
||||
_.forEach([1, 2, 3], function(num){ answers.push(num); });
|
||||
equals(answers.join(', '), '1, 2, 3', 'aliased as "forEach"');
|
||||
|
||||
answers = [];
|
||||
var obj = {one : 1, two : 2, three : 3};
|
||||
obj.constructor.prototype.four = 4;
|
||||
_.each(obj, function(value, key){ answers.push(key); });
|
||||
equals(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
|
||||
delete obj.constructor.prototype.four;
|
||||
|
||||
answer = null;
|
||||
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
|
||||
ok(answer, 'can reference the original collection from inside the iterator');
|
||||
|
||||
answers = 0;
|
||||
_.each(null, function(){ ++answers; });
|
||||
equals(answers, 0, 'handles a null properly');
|
||||
});
|
||||
|
||||
test('collections: map', function() {
|
||||
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
|
||||
equals(doubled.join(', '), '2, 4, 6', 'doubled numbers');
|
||||
|
||||
doubled = _.collect([1, 2, 3], function(num){ return num * 2; });
|
||||
equals(doubled.join(', '), '2, 4, 6', 'aliased as "collect"');
|
||||
|
||||
var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3});
|
||||
equals(tripled.join(', '), '3, 6, 9', 'tripled numbers with context');
|
||||
|
||||
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
|
||||
equals(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
|
||||
|
||||
var ids = _.map($('div.underscore-test').children(), function(n){ return n.id; });
|
||||
ok(_.include(ids, 'qunit-header'), 'can use collection methods on NodeLists');
|
||||
|
||||
var ids = _.map(document.images, function(n){ return n.id; });
|
||||
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
|
||||
|
||||
var ifnull = _.map(null, function(){});
|
||||
ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');
|
||||
|
||||
var length = _.map(Array(2), function(v) { return v; }).length;
|
||||
equals(length, 2, "can preserve a sparse array's length");
|
||||
});
|
||||
|
||||
test('collections: reduce', function() {
|
||||
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
|
||||
equals(sum, 6, 'can sum up an array');
|
||||
|
||||
var context = {multiplier : 3};
|
||||
sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context);
|
||||
equals(sum, 18, 'can reduce with a context object');
|
||||
|
||||
sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0);
|
||||
equals(sum, 6, 'aliased as "inject"');
|
||||
|
||||
sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0);
|
||||
equals(sum, 6, 'OO-style reduce');
|
||||
|
||||
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; });
|
||||
equals(sum, 6, 'default initial value');
|
||||
|
||||
var ifnull;
|
||||
try {
|
||||
_.reduce(null, function(){});
|
||||
} catch (ex) {
|
||||
ifnull = ex;
|
||||
}
|
||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||
|
||||
ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
|
||||
equals(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
|
||||
raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
||||
|
||||
var sparseArray = [];
|
||||
sparseArray[0] = 20;
|
||||
sparseArray[2] = -5;
|
||||
equals(_.reduce(sparseArray, function(a, b){ return a - b; }), 25, 'initially-sparse arrays with no memo');
|
||||
});
|
||||
|
||||
test('collections: reduceRight', function() {
|
||||
var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
|
||||
equals(list, 'bazbarfoo', 'can perform right folds');
|
||||
|
||||
var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
|
||||
equals(list, 'bazbarfoo', 'aliased as "foldr"');
|
||||
|
||||
var list = _.foldr(["foo", "bar", "baz"], function(memo, str){ return memo + str; });
|
||||
equals(list, 'bazbarfoo', 'default initial value');
|
||||
|
||||
var ifnull;
|
||||
try {
|
||||
_.reduceRight(null, function(){});
|
||||
} catch (ex) {
|
||||
ifnull = ex;
|
||||
}
|
||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||
|
||||
ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
|
||||
|
||||
equals(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
|
||||
raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
||||
|
||||
var sparseArray = [];
|
||||
sparseArray[0] = 20;
|
||||
sparseArray[2] = -5;
|
||||
equals(_.reduceRight(sparseArray, function(a, b){ return a - b; }), -25, 'initially-sparse arrays with no memo');
|
||||
});
|
||||
|
||||
test('collections: detect', function() {
|
||||
var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });
|
||||
equals(result, 2, 'found the first "2" and broke the loop');
|
||||
});
|
||||
|
||||
test('collections: select', function() {
|
||||
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
||||
equals(evens.join(', '), '2, 4, 6', 'selected each even number');
|
||||
|
||||
evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
||||
equals(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
|
||||
});
|
||||
|
||||
test('collections: reject', function() {
|
||||
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
||||
equals(odds.join(', '), '1, 3, 5', 'rejected each even number');
|
||||
});
|
||||
|
||||
test('collections: all', function() {
|
||||
ok(_.all([], _.identity), 'the empty set');
|
||||
ok(_.all([true, true, true], _.identity), 'all true values');
|
||||
ok(!_.all([true, false, true], _.identity), 'one false value');
|
||||
ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers');
|
||||
ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number');
|
||||
ok(_.every([true, true, true], _.identity), 'aliased as "every"');
|
||||
});
|
||||
|
||||
test('collections: any', function() {
|
||||
var nativeSome = Array.prototype.some;
|
||||
Array.prototype.some = null;
|
||||
ok(!_.any([]), 'the empty set');
|
||||
ok(!_.any([false, false, false]), 'all false values');
|
||||
ok(_.any([false, false, true]), 'one true value');
|
||||
ok(_.any([null, 0, 'yes', false]), 'a string');
|
||||
ok(!_.any([null, 0, '', false]), 'falsy values');
|
||||
ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers');
|
||||
ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number');
|
||||
ok(_.some([false, false, true]), 'aliased as "some"');
|
||||
Array.prototype.some = nativeSome;
|
||||
});
|
||||
|
||||
test('collections: include', function() {
|
||||
ok(_.include([1,2,3], 2), 'two is in the array');
|
||||
ok(!_.include([1,3,9], 2), 'two is not in the array');
|
||||
ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');
|
||||
ok(_([1,2,3]).include(2), 'OO-style include');
|
||||
});
|
||||
|
||||
test('collections: invoke', function() {
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var result = _.invoke(list, 'sort');
|
||||
equals(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
||||
equals(result[1].join(', '), '1, 2, 3', 'second array sorted');
|
||||
});
|
||||
|
||||
test('collections: invoke w/ function reference', function() {
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var result = _.invoke(list, Array.prototype.sort);
|
||||
equals(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
||||
equals(result[1].join(', '), '1, 2, 3', 'second array sorted');
|
||||
});
|
||||
|
||||
// Relevant when using ClojureScript
|
||||
test('collections: invoke when strings have a call method', function() {
|
||||
String.prototype.call = function(){return 42;}
|
||||
var list = [[5, 1, 7], [3, 2, 1]];
|
||||
var s = "foo";
|
||||
equals(s.call(), 42, "call function exists");
|
||||
var result = _.invoke(list, 'sort');
|
||||
equals(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
||||
equals(result[1].join(', '), '1, 2, 3', 'second array sorted');
|
||||
delete String.prototype.call;
|
||||
equals(s.call, undefined, "call function removed");
|
||||
});
|
||||
|
||||
test('collections: pluck', function() {
|
||||
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];
|
||||
equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
|
||||
});
|
||||
|
||||
test('collections: max', function() {
|
||||
equals(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
|
||||
|
||||
var neg = _.max([1, 2, 3], function(num){ return -num; });
|
||||
equals(neg, 1, 'can perform a computation-based max');
|
||||
|
||||
equals(-Infinity, _.max({}), 'Maximum value of an empty object');
|
||||
equals(-Infinity, _.max([]), 'Maximum value of an empty array');
|
||||
});
|
||||
|
||||
test('collections: min', function() {
|
||||
equals(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
|
||||
|
||||
var neg = _.min([1, 2, 3], function(num){ return -num; });
|
||||
equals(neg, 3, 'can perform a computation-based min');
|
||||
|
||||
equals(Infinity, _.min({}), 'Minimum value of an empty object');
|
||||
equals(Infinity, _.min([]), 'Minimum value of an empty array');
|
||||
});
|
||||
|
||||
test('collections: sortBy', function() {
|
||||
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
|
||||
people = _.sortBy(people, function(person){ return person.age; });
|
||||
equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
|
||||
});
|
||||
|
||||
test('collections: groupBy', function() {
|
||||
var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; });
|
||||
ok('0' in parity && '1' in parity, 'created a group for each value');
|
||||
equals(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group');
|
||||
|
||||
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
|
||||
var grouped = _.groupBy(list, 'length');
|
||||
equals(grouped['3'].join(' '), 'one two six ten');
|
||||
equals(grouped['4'].join(' '), 'four five nine');
|
||||
equals(grouped['5'].join(' '), 'three seven eight');
|
||||
});
|
||||
|
||||
test('collections: sortedIndex', function() {
|
||||
var numbers = [10, 20, 30, 40, 50], num = 35;
|
||||
var index = _.sortedIndex(numbers, num);
|
||||
equals(index, 3, '35 should be inserted at index 3');
|
||||
});
|
||||
|
||||
test('collections: shuffle', function() {
|
||||
var numbers = _.range(10);
|
||||
var shuffled = _.shuffle(numbers).sort();
|
||||
notStrictEqual(numbers, shuffled, 'original object is unmodified');
|
||||
equals(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');
|
||||
});
|
||||
|
||||
test('collections: toArray', function() {
|
||||
ok(!_.isArray(arguments), 'arguments object is not an array');
|
||||
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
|
||||
var a = [1,2,3];
|
||||
ok(_.toArray(a) !== a, 'array is cloned');
|
||||
equals(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements');
|
||||
|
||||
var numbers = _.toArray({one : 1, two : 2, three : 3});
|
||||
equals(numbers.join(', '), '1, 2, 3', 'object flattened into array');
|
||||
});
|
||||
|
||||
test('collections: size', function() {
|
||||
equals(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
|
||||
});
|
||||
|
||||
});
|
198
node_modules/piler/node_modules/underscore.string/test/test_underscore/functions.js
generated
vendored
Normal file
198
node_modules/piler/node_modules/underscore.string/test/test_underscore/functions.js
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Functions");
|
||||
|
||||
test("functions: bind", function() {
|
||||
var context = {name : 'moe'};
|
||||
var func = function(arg) { return "name: " + (this.name || arg); };
|
||||
var bound = _.bind(func, context);
|
||||
equals(bound(), 'name: moe', 'can bind a function to a context');
|
||||
|
||||
bound = _(func).bind(context);
|
||||
equals(bound(), 'name: moe', 'can do OO-style binding');
|
||||
|
||||
bound = _.bind(func, null, 'curly');
|
||||
equals(bound(), 'name: curly', 'can bind without specifying a context');
|
||||
|
||||
func = function(salutation, name) { return salutation + ': ' + name; };
|
||||
func = _.bind(func, this, 'hello');
|
||||
equals(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
||||
|
||||
var func = _.bind(func, this, 'curly');
|
||||
equals(func(), 'hello: curly', 'the function was completely applied in advance');
|
||||
|
||||
var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
||||
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
||||
equals(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
||||
|
||||
func = function(context, message) { equals(this, context, message); };
|
||||
_.bind(func, 0, 0, 'can bind a function to `0`')();
|
||||
_.bind(func, '', '', 'can bind a function to an empty string')();
|
||||
_.bind(func, false, false, 'can bind a function to `false`')();
|
||||
|
||||
// These tests are only meaningful when using a browser without a native bind function
|
||||
// To test this with a modern browser, set underscore's nativeBind to undefined
|
||||
var F = function () { return this; };
|
||||
var Boundf = _.bind(F, {hello: "moe curly"});
|
||||
equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5");
|
||||
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
|
||||
});
|
||||
|
||||
test("functions: bindAll", function() {
|
||||
var curly = {name : 'curly'}, moe = {
|
||||
name : 'moe',
|
||||
getName : function() { return 'name: ' + this.name; },
|
||||
sayHi : function() { return 'hi: ' + this.name; }
|
||||
};
|
||||
curly.getName = moe.getName;
|
||||
_.bindAll(moe, 'getName', 'sayHi');
|
||||
curly.sayHi = moe.sayHi;
|
||||
equals(curly.getName(), 'name: curly', 'unbound function is bound to current object');
|
||||
equals(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
||||
|
||||
curly = {name : 'curly'};
|
||||
moe = {
|
||||
name : 'moe',
|
||||
getName : function() { return 'name: ' + this.name; },
|
||||
sayHi : function() { return 'hi: ' + this.name; }
|
||||
};
|
||||
_.bindAll(moe);
|
||||
curly.sayHi = moe.sayHi;
|
||||
equals(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
|
||||
});
|
||||
|
||||
test("functions: memoize", function() {
|
||||
var fib = function(n) {
|
||||
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
||||
};
|
||||
var fastFib = _.memoize(fib);
|
||||
equals(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||
equals(fastFib(10), 55, 'a memoized version of fibonacci produces identical results');
|
||||
|
||||
var o = function(str) {
|
||||
return str;
|
||||
};
|
||||
var fastO = _.memoize(o);
|
||||
equals(o('toString'), 'toString', 'checks hasOwnProperty');
|
||||
equals(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
||||
});
|
||||
|
||||
asyncTest("functions: delay", 2, function() {
|
||||
var delayed = false;
|
||||
_.delay(function(){ delayed = true; }, 100);
|
||||
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
||||
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
||||
});
|
||||
|
||||
asyncTest("functions: defer", 1, function() {
|
||||
var deferred = false;
|
||||
_.defer(function(bool){ deferred = bool; }, true);
|
||||
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
|
||||
});
|
||||
|
||||
asyncTest("functions: throttle", 2, function() {
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
throttledIncr(); throttledIncr(); throttledIncr();
|
||||
setTimeout(throttledIncr, 70);
|
||||
setTimeout(throttledIncr, 120);
|
||||
setTimeout(throttledIncr, 140);
|
||||
setTimeout(throttledIncr, 190);
|
||||
setTimeout(throttledIncr, 220);
|
||||
setTimeout(throttledIncr, 240);
|
||||
_.delay(function(){ ok(counter == 1, "incr was called immediately"); }, 30);
|
||||
_.delay(function(){ ok(counter == 4, "incr was throttled"); start(); }, 400);
|
||||
});
|
||||
|
||||
asyncTest("functions: throttle arguments", 2, function() {
|
||||
var value = 0;
|
||||
var update = function(val){ value = val; };
|
||||
var throttledUpdate = _.throttle(update, 100);
|
||||
throttledUpdate(1); throttledUpdate(2); throttledUpdate(3);
|
||||
setTimeout(function(){ throttledUpdate(4); }, 120);
|
||||
setTimeout(function(){ throttledUpdate(5); }, 140);
|
||||
setTimeout(function(){ throttledUpdate(6); }, 250);
|
||||
_.delay(function(){ equals(value, 1, "updated to latest value"); }, 40);
|
||||
_.delay(function(){ equals(value, 6, "updated to latest value"); start(); }, 400);
|
||||
});
|
||||
|
||||
asyncTest("functions: throttle once", 1, function() {
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
throttledIncr();
|
||||
_.delay(function(){ ok(counter == 1, "incr was called once"); start(); }, 220);
|
||||
});
|
||||
|
||||
asyncTest("functions: throttle twice", 1, function() {
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
throttledIncr(); throttledIncr();
|
||||
_.delay(function(){ ok(counter == 2, "incr was called twice"); start(); }, 220);
|
||||
});
|
||||
|
||||
asyncTest("functions: debounce", 1, function() {
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var debouncedIncr = _.debounce(incr, 50);
|
||||
debouncedIncr(); debouncedIncr(); debouncedIncr();
|
||||
setTimeout(debouncedIncr, 30);
|
||||
setTimeout(debouncedIncr, 60);
|
||||
setTimeout(debouncedIncr, 90);
|
||||
setTimeout(debouncedIncr, 120);
|
||||
setTimeout(debouncedIncr, 150);
|
||||
_.delay(function(){ ok(counter == 1, "incr was debounced"); start(); }, 220);
|
||||
});
|
||||
|
||||
test("functions: once", function() {
|
||||
var num = 0;
|
||||
var increment = _.once(function(){ num++; });
|
||||
increment();
|
||||
increment();
|
||||
equals(num, 1);
|
||||
});
|
||||
|
||||
test("functions: wrap", function() {
|
||||
var greet = function(name){ return "hi: " + name; };
|
||||
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
||||
equals(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
|
||||
|
||||
var inner = function(){ return "Hello "; };
|
||||
var obj = {name : "Moe"};
|
||||
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
||||
equals(obj.hi(), "Hello Moe");
|
||||
|
||||
var noop = function(){};
|
||||
var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });
|
||||
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
||||
same(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||
});
|
||||
|
||||
test("functions: compose", function() {
|
||||
var greet = function(name){ return "hi: " + name; };
|
||||
var exclaim = function(sentence){ return sentence + '!'; };
|
||||
var composed = _.compose(exclaim, greet);
|
||||
equals(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
||||
|
||||
composed = _.compose(greet, exclaim);
|
||||
equals(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
||||
});
|
||||
|
||||
test("functions: after", function() {
|
||||
var testAfter = function(afterAmount, timesCalled) {
|
||||
var afterCalled = 0;
|
||||
var after = _.after(afterAmount, function() {
|
||||
afterCalled++;
|
||||
});
|
||||
while (timesCalled--) after();
|
||||
return afterCalled;
|
||||
};
|
||||
|
||||
equals(testAfter(5, 5), 1, "after(N) should fire after being called N times");
|
||||
equals(testAfter(5, 4), 0, "after(N) should not fire unless called N times");
|
||||
equals(testAfter(0, 0), 1, "after(0) should fire immediately");
|
||||
});
|
||||
|
||||
});
|
535
node_modules/piler/node_modules/underscore.string/test/test_underscore/objects.js
generated
vendored
Normal file
535
node_modules/piler/node_modules/underscore.string/test/test_underscore/objects.js
generated
vendored
Normal file
@ -0,0 +1,535 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Objects");
|
||||
|
||||
test("objects: keys", function() {
|
||||
var exception = /object/;
|
||||
equals(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object');
|
||||
// the test above is not safe because it relies on for-in enumeration order
|
||||
var a = []; a[1] = 0;
|
||||
equals(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95');
|
||||
raises(function() { _.keys(null); }, exception, 'throws an error for `null` values');
|
||||
raises(function() { _.keys(void 0); }, exception, 'throws an error for `undefined` values');
|
||||
raises(function() { _.keys(1); }, exception, 'throws an error for number primitives');
|
||||
raises(function() { _.keys('a'); }, exception, 'throws an error for string primitives');
|
||||
raises(function() { _.keys(true); }, exception, 'throws an error for boolean primitives');
|
||||
});
|
||||
|
||||
test("objects: values", function() {
|
||||
equals(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object');
|
||||
});
|
||||
|
||||
test("objects: functions", function() {
|
||||
var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce};
|
||||
ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object');
|
||||
|
||||
var Animal = function(){};
|
||||
Animal.prototype.run = function(){};
|
||||
equals(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');
|
||||
});
|
||||
|
||||
test("objects: extend", function() {
|
||||
var result;
|
||||
equals(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');
|
||||
equals(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');
|
||||
equals(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden');
|
||||
result = _.extend({x:'x'}, {a:'a'}, {b:'b'});
|
||||
ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects');
|
||||
result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'});
|
||||
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
|
||||
result = _.extend({}, {a: void 0, b: null});
|
||||
equals(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
|
||||
});
|
||||
|
||||
test("objects: defaults", function() {
|
||||
var result;
|
||||
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
|
||||
|
||||
_.defaults(options, {zero: 1, one: 10, twenty: 20});
|
||||
equals(options.zero, 0, 'value exists');
|
||||
equals(options.one, 1, 'value exists');
|
||||
equals(options.twenty, 20, 'default applied');
|
||||
|
||||
_.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"});
|
||||
equals(options.empty, "", 'value exists');
|
||||
ok(_.isNaN(options.nan), "NaN isn't overridden");
|
||||
equals(options.word, "word", 'new value is added, first one wins');
|
||||
});
|
||||
|
||||
test("objects: clone", function() {
|
||||
var moe = {name : 'moe', lucky : [13, 27, 34]};
|
||||
var clone = _.clone(moe);
|
||||
equals(clone.name, 'moe', 'the clone as the attributes of the original');
|
||||
|
||||
clone.name = 'curly';
|
||||
ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original');
|
||||
|
||||
clone.lucky.push(101);
|
||||
equals(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original');
|
||||
|
||||
equals(_.clone(undefined), void 0, 'non objects should not be changed by clone');
|
||||
equals(_.clone(1), 1, 'non objects should not be changed by clone');
|
||||
equals(_.clone(null), null, 'non objects should not be changed by clone');
|
||||
});
|
||||
|
||||
test("objects: isEqual", function() {
|
||||
function First() {
|
||||
this.value = 1;
|
||||
}
|
||||
First.prototype.value = 1;
|
||||
function Second() {
|
||||
this.value = 1;
|
||||
}
|
||||
Second.prototype.value = 2;
|
||||
|
||||
// Basic equality and identity comparisons.
|
||||
ok(_.isEqual(null, null), "`null` is equal to `null`");
|
||||
ok(_.isEqual(), "`undefined` is equal to `undefined`");
|
||||
|
||||
ok(!_.isEqual(0, -0), "`0` is not equal to `-0`");
|
||||
ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`");
|
||||
ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`");
|
||||
ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`");
|
||||
|
||||
// String object and primitive comparisons.
|
||||
ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal");
|
||||
ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal");
|
||||
ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal");
|
||||
ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives");
|
||||
|
||||
ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal");
|
||||
ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal");
|
||||
ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal");
|
||||
|
||||
// Number object and primitive comparisons.
|
||||
ok(_.isEqual(75, 75), "Identical number primitives are equal");
|
||||
ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal");
|
||||
ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal");
|
||||
ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives");
|
||||
ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal");
|
||||
ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`");
|
||||
|
||||
ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal");
|
||||
ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal");
|
||||
|
||||
// Comparisons involving `NaN`.
|
||||
ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`");
|
||||
ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`");
|
||||
ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`");
|
||||
ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`");
|
||||
|
||||
// Boolean object and primitive comparisons.
|
||||
ok(_.isEqual(true, true), "Identical boolean primitives are equal");
|
||||
ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal");
|
||||
ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal");
|
||||
ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans");
|
||||
ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal");
|
||||
|
||||
// Common type coercions.
|
||||
ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`");
|
||||
ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal");
|
||||
ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal");
|
||||
ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values");
|
||||
ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal");
|
||||
ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal");
|
||||
ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal");
|
||||
ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal");
|
||||
ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal");
|
||||
|
||||
// Dates.
|
||||
ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal");
|
||||
ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal");
|
||||
ok(!_.isEqual(new Date(2009, 11, 13), {
|
||||
getTime: function(){
|
||||
return 12606876e5;
|
||||
}
|
||||
}), "Date objects and objects with a `getTime` method are not equal");
|
||||
ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal");
|
||||
|
||||
// Functions.
|
||||
ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal");
|
||||
|
||||
// RegExps.
|
||||
ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal");
|
||||
ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal");
|
||||
ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal");
|
||||
ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps");
|
||||
ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal");
|
||||
|
||||
// Empty arrays, array-like objects, and object literals.
|
||||
ok(_.isEqual({}, {}), "Empty object literals are equal");
|
||||
ok(_.isEqual([], []), "Empty array literals are equal");
|
||||
ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
|
||||
ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
|
||||
ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");
|
||||
|
||||
ok(!_.isEqual({}, []), "Object literals and array literals are not equal");
|
||||
ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays");
|
||||
|
||||
// Arrays with primitive and object values.
|
||||
ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal");
|
||||
ok(_.isEqual([/Moe/g, new Date(2009, 9, 25)], [/Moe/g, new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal");
|
||||
|
||||
// Multi-dimensional arrays.
|
||||
var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
|
||||
var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
|
||||
ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared");
|
||||
|
||||
// Overwrite the methods defined in ES 5.1 section 15.4.4.
|
||||
a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;
|
||||
b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;
|
||||
|
||||
// Array elements and properties.
|
||||
ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal");
|
||||
a.push("White Rocks");
|
||||
ok(!_.isEqual(a, b), "Arrays of different lengths are not equal");
|
||||
a.push("East Boulder");
|
||||
b.push("Gunbarrel Ranch", "Teller Farm");
|
||||
ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal");
|
||||
|
||||
// Sparse arrays.
|
||||
ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
|
||||
ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty");
|
||||
|
||||
// According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined`
|
||||
// elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined`
|
||||
// values are equivalent.
|
||||
if (0 in [undefined]) {
|
||||
ok(!_.isEqual(Array(3), [undefined, undefined, undefined]), "Sparse and dense arrays are not equal");
|
||||
ok(!_.isEqual([undefined, undefined, undefined], Array(3)), "Commutative equality is implemented for sparse and dense arrays");
|
||||
}
|
||||
|
||||
// Simple objects.
|
||||
ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal");
|
||||
ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal");
|
||||
ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal");
|
||||
ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal");
|
||||
ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal");
|
||||
ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects");
|
||||
ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent");
|
||||
|
||||
// `A` contains nested objects and arrays.
|
||||
a = {
|
||||
name: new String("Moe Howard"),
|
||||
age: new Number(77),
|
||||
stooge: true,
|
||||
hobbies: ["acting"],
|
||||
film: {
|
||||
name: "Sing a Song of Six Pants",
|
||||
release: new Date(1947, 9, 30),
|
||||
stars: [new String("Larry Fine"), "Shemp Howard"],
|
||||
minutes: new Number(16),
|
||||
seconds: 54
|
||||
}
|
||||
};
|
||||
|
||||
// `B` contains equivalent nested objects and arrays.
|
||||
b = {
|
||||
name: new String("Moe Howard"),
|
||||
age: new Number(77),
|
||||
stooge: true,
|
||||
hobbies: ["acting"],
|
||||
film: {
|
||||
name: "Sing a Song of Six Pants",
|
||||
release: new Date(1947, 9, 30),
|
||||
stars: [new String("Larry Fine"), "Shemp Howard"],
|
||||
minutes: new Number(16),
|
||||
seconds: 54
|
||||
}
|
||||
};
|
||||
ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared");
|
||||
|
||||
// Instances.
|
||||
ok(_.isEqual(new First, new First), "Object instances are equal");
|
||||
ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal");
|
||||
ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal");
|
||||
ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined");
|
||||
|
||||
// Circular Arrays.
|
||||
(a = []).push(a);
|
||||
(b = []).push(b);
|
||||
ok(_.isEqual(a, b), "Arrays containing circular references are equal");
|
||||
a.push(new String("Larry"));
|
||||
b.push(new String("Larry"));
|
||||
ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal");
|
||||
a.push("Shemp");
|
||||
b.push("Curly");
|
||||
ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal");
|
||||
|
||||
// Circular Objects.
|
||||
a = {abc: null};
|
||||
b = {abc: null};
|
||||
a.abc = a;
|
||||
b.abc = b;
|
||||
ok(_.isEqual(a, b), "Objects containing circular references are equal");
|
||||
a.def = 75;
|
||||
b.def = 75;
|
||||
ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal");
|
||||
a.def = new Number(75);
|
||||
b.def = new Number(63);
|
||||
ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal");
|
||||
|
||||
// Cyclic Structures.
|
||||
a = [{abc: null}];
|
||||
b = [{abc: null}];
|
||||
(a[0].abc = a).push(a);
|
||||
(b[0].abc = b).push(b);
|
||||
ok(_.isEqual(a, b), "Cyclic structures are equal");
|
||||
a[0].def = "Larry";
|
||||
b[0].def = "Larry";
|
||||
ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal");
|
||||
a[0].def = new String("Larry");
|
||||
b[0].def = new String("Curly");
|
||||
ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal");
|
||||
|
||||
// Complex Circular References.
|
||||
a = {foo: {b: {foo: {c: {foo: null}}}}};
|
||||
b = {foo: {b: {foo: {c: {foo: null}}}}};
|
||||
a.foo.b.foo.c.foo = a;
|
||||
b.foo.b.foo.c.foo = b;
|
||||
ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal");
|
||||
|
||||
// Chaining.
|
||||
ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');
|
||||
equals(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained');
|
||||
|
||||
// Custom `isEqual` methods.
|
||||
var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}};
|
||||
var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}};
|
||||
|
||||
ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods');
|
||||
ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods');
|
||||
ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal');
|
||||
ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods');
|
||||
|
||||
// Custom `isEqual` methods - comparing different types
|
||||
LocalizedString = (function() {
|
||||
function LocalizedString(id) { this.id = id; this.string = (this.id===10)? 'Bonjour': ''; }
|
||||
LocalizedString.prototype.isEqual = function(that) {
|
||||
if (_.isString(that)) return this.string == that;
|
||||
else if (that instanceof LocalizedString) return this.id == that.id;
|
||||
return false;
|
||||
};
|
||||
return LocalizedString;
|
||||
})();
|
||||
var localized_string1 = new LocalizedString(10), localized_string2 = new LocalizedString(10), localized_string3 = new LocalizedString(11);
|
||||
ok(_.isEqual(localized_string1, localized_string2), 'comparing same typed instances with same ids');
|
||||
ok(!_.isEqual(localized_string1, localized_string3), 'comparing same typed instances with different ids');
|
||||
ok(_.isEqual(localized_string1, 'Bonjour'), 'comparing different typed instances with same values');
|
||||
ok(_.isEqual('Bonjour', localized_string1), 'comparing different typed instances with same values');
|
||||
ok(!_.isEqual('Bonjour', localized_string3), 'comparing two localized strings with different ids');
|
||||
ok(!_.isEqual(localized_string1, 'Au revoir'), 'comparing different typed instances with different values');
|
||||
ok(!_.isEqual('Au revoir', localized_string1), 'comparing different typed instances with different values');
|
||||
|
||||
// Custom `isEqual` methods - comparing with serialized data
|
||||
Date.prototype.toJSON = function() {
|
||||
return {
|
||||
_type:'Date',
|
||||
year:this.getUTCFullYear(),
|
||||
month:this.getUTCMonth(),
|
||||
day:this.getUTCDate(),
|
||||
hours:this.getUTCHours(),
|
||||
minutes:this.getUTCMinutes(),
|
||||
seconds:this.getUTCSeconds()
|
||||
};
|
||||
};
|
||||
Date.prototype.isEqual = function(that) {
|
||||
var this_date_components = this.toJSON();
|
||||
var that_date_components = (that instanceof Date) ? that.toJSON() : that;
|
||||
delete this_date_components['_type']; delete that_date_components['_type']
|
||||
return _.isEqual(this_date_components, that_date_components);
|
||||
};
|
||||
|
||||
var date = new Date();
|
||||
var date_json = {
|
||||
_type:'Date',
|
||||
year:date.getUTCFullYear(),
|
||||
month:date.getUTCMonth(),
|
||||
day:date.getUTCDate(),
|
||||
hours:date.getUTCHours(),
|
||||
minutes:date.getUTCMinutes(),
|
||||
seconds:date.getUTCSeconds()
|
||||
};
|
||||
|
||||
ok(_.isEqual(date_json, date), 'serialized date matches date');
|
||||
ok(_.isEqual(date, date_json), 'date matches serialized date');
|
||||
});
|
||||
|
||||
test("objects: isEmpty", function() {
|
||||
ok(!_([1]).isEmpty(), '[1] is not empty');
|
||||
ok(_.isEmpty([]), '[] is empty');
|
||||
ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');
|
||||
ok(_.isEmpty({}), '{} is empty');
|
||||
ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty');
|
||||
ok(_.isEmpty(null), 'null is empty');
|
||||
ok(_.isEmpty(), 'undefined is empty');
|
||||
ok(_.isEmpty(''), 'the empty string is empty');
|
||||
ok(!_.isEmpty('moe'), 'but other strings are not');
|
||||
|
||||
var obj = {one : 1};
|
||||
delete obj.one;
|
||||
ok(_.isEmpty(obj), 'deleting all the keys from an object empties it');
|
||||
});
|
||||
|
||||
// Setup remote variables for iFrame tests.
|
||||
var iframe = document.createElement('iframe');
|
||||
jQuery(iframe).appendTo(document.body);
|
||||
var iDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||||
iDoc.write(
|
||||
"<script>\
|
||||
parent.iElement = document.createElement('div');\
|
||||
parent.iArguments = (function(){ return arguments; })(1, 2, 3);\
|
||||
parent.iArray = [1, 2, 3];\
|
||||
parent.iString = new String('hello');\
|
||||
parent.iNumber = new Number(100);\
|
||||
parent.iFunction = (function(){});\
|
||||
parent.iDate = new Date();\
|
||||
parent.iRegExp = /hi/;\
|
||||
parent.iNaN = NaN;\
|
||||
parent.iNull = null;\
|
||||
parent.iBoolean = new Boolean(false);\
|
||||
parent.iUndefined = undefined;\
|
||||
</script>"
|
||||
);
|
||||
iDoc.close();
|
||||
|
||||
test("objects: isElement", function() {
|
||||
ok(!_.isElement('div'), 'strings are not dom elements');
|
||||
ok(_.isElement($('html')[0]), 'the html tag is a DOM element');
|
||||
ok(_.isElement(iElement), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isArguments", function() {
|
||||
var args = (function(){ return arguments; })(1, 2, 3);
|
||||
ok(!_.isArguments('string'), 'a string is not an arguments object');
|
||||
ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');
|
||||
ok(_.isArguments(args), 'but the arguments object is an arguments object');
|
||||
ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array');
|
||||
ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.');
|
||||
ok(_.isArguments(iArguments), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isObject", function() {
|
||||
ok(_.isObject(arguments), 'the arguments object is object');
|
||||
ok(_.isObject([1, 2, 3]), 'and arrays');
|
||||
ok(_.isObject($('html')[0]), 'and DOM element');
|
||||
ok(_.isObject(iElement), 'even from another frame');
|
||||
ok(_.isObject(function () {}), 'and functions');
|
||||
ok(_.isObject(iFunction), 'even from another frame');
|
||||
ok(!_.isObject(null), 'but not null');
|
||||
ok(!_.isObject(undefined), 'and not undefined');
|
||||
ok(!_.isObject('string'), 'and not string');
|
||||
ok(!_.isObject(12), 'and not number');
|
||||
ok(!_.isObject(true), 'and not boolean');
|
||||
ok(_.isObject(new String('string')), 'but new String()');
|
||||
});
|
||||
|
||||
test("objects: isArray", function() {
|
||||
ok(!_.isArray(arguments), 'the arguments object is not an array');
|
||||
ok(_.isArray([1, 2, 3]), 'but arrays are');
|
||||
ok(_.isArray(iArray), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isString", function() {
|
||||
ok(!_.isString(document.body), 'the document body is not a string');
|
||||
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
|
||||
ok(_.isString(iString), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isNumber", function() {
|
||||
ok(!_.isNumber('string'), 'a string is not a number');
|
||||
ok(!_.isNumber(arguments), 'the arguments object is not a number');
|
||||
ok(!_.isNumber(undefined), 'undefined is not a number');
|
||||
ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are');
|
||||
ok(_.isNumber(NaN), 'NaN *is* a number');
|
||||
ok(_.isNumber(Infinity), 'Infinity is a number');
|
||||
ok(_.isNumber(iNumber), 'even from another frame');
|
||||
ok(!_.isNumber('1'), 'numeric strings are not numbers');
|
||||
});
|
||||
|
||||
test("objects: isBoolean", function() {
|
||||
ok(!_.isBoolean(2), 'a number is not a boolean');
|
||||
ok(!_.isBoolean("string"), 'a string is not a boolean');
|
||||
ok(!_.isBoolean("false"), 'the string "false" is not a boolean');
|
||||
ok(!_.isBoolean("true"), 'the string "true" is not a boolean');
|
||||
ok(!_.isBoolean(arguments), 'the arguments object is not a boolean');
|
||||
ok(!_.isBoolean(undefined), 'undefined is not a boolean');
|
||||
ok(!_.isBoolean(NaN), 'NaN is not a boolean');
|
||||
ok(!_.isBoolean(null), 'null is not a boolean');
|
||||
ok(_.isBoolean(true), 'but true is');
|
||||
ok(_.isBoolean(false), 'and so is false');
|
||||
ok(_.isBoolean(iBoolean), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isFunction", function() {
|
||||
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
|
||||
ok(!_.isFunction('moe'), 'strings are not functions');
|
||||
ok(_.isFunction(_.isFunction), 'but functions are');
|
||||
ok(_.isFunction(iFunction), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isDate", function() {
|
||||
ok(!_.isDate(100), 'numbers are not dates');
|
||||
ok(!_.isDate({}), 'objects are not dates');
|
||||
ok(_.isDate(new Date()), 'but dates are');
|
||||
ok(_.isDate(iDate), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isRegExp", function() {
|
||||
ok(!_.isRegExp(_.identity), 'functions are not RegExps');
|
||||
ok(_.isRegExp(/identity/), 'but RegExps are');
|
||||
ok(_.isRegExp(iRegExp), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isNaN", function() {
|
||||
ok(!_.isNaN(undefined), 'undefined is not NaN');
|
||||
ok(!_.isNaN(null), 'null is not NaN');
|
||||
ok(!_.isNaN(0), '0 is not NaN');
|
||||
ok(_.isNaN(NaN), 'but NaN is');
|
||||
ok(_.isNaN(iNaN), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isNull", function() {
|
||||
ok(!_.isNull(undefined), 'undefined is not null');
|
||||
ok(!_.isNull(NaN), 'NaN is not null');
|
||||
ok(_.isNull(null), 'but null is');
|
||||
ok(_.isNull(iNull), 'even from another frame');
|
||||
});
|
||||
|
||||
test("objects: isUndefined", function() {
|
||||
ok(!_.isUndefined(1), 'numbers are defined');
|
||||
ok(!_.isUndefined(null), 'null is defined');
|
||||
ok(!_.isUndefined(false), 'false is defined');
|
||||
ok(!_.isUndefined(NaN), 'NaN is defined');
|
||||
ok(_.isUndefined(), 'nothing is undefined');
|
||||
ok(_.isUndefined(undefined), 'undefined is undefined');
|
||||
ok(_.isUndefined(iUndefined), 'even from another frame');
|
||||
});
|
||||
|
||||
if (window.ActiveXObject) {
|
||||
test("objects: IE host objects", function() {
|
||||
var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
|
||||
ok(!_.isNumber(xml));
|
||||
ok(!_.isBoolean(xml));
|
||||
ok(!_.isNaN(xml));
|
||||
ok(!_.isFunction(xml));
|
||||
ok(!_.isNull(xml));
|
||||
ok(!_.isUndefined(xml));
|
||||
});
|
||||
}
|
||||
|
||||
test("objects: tap", function() {
|
||||
var intercepted = null;
|
||||
var interceptor = function(obj) { intercepted = obj; };
|
||||
var returned = _.tap(1, interceptor);
|
||||
equals(intercepted, 1, "passes tapped object to interceptor");
|
||||
equals(returned, 1, "returns tapped object");
|
||||
|
||||
returned = _([1,2,3]).chain().
|
||||
map(function(n){ return n * 2; }).
|
||||
max().
|
||||
tap(interceptor).
|
||||
value();
|
||||
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
|
||||
});
|
||||
});
|
70
node_modules/piler/node_modules/underscore.string/test/test_underscore/speed.js
generated
vendored
Normal file
70
node_modules/piler/node_modules/underscore.string/test/test_underscore/speed.js
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
(function() {
|
||||
|
||||
var numbers = [];
|
||||
for (var i=0; i<1000; i++) numbers.push(i);
|
||||
var objects = _.map(numbers, function(n){ return {num : n}; });
|
||||
var randomized = _.sortBy(numbers, function(){ return Math.random(); });
|
||||
|
||||
JSLitmus.test('_.each()', function() {
|
||||
var timesTwo = [];
|
||||
_.each(numbers, function(num){ timesTwo.push(num * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('_(list).each()', function() {
|
||||
var timesTwo = [];
|
||||
_(numbers).each(function(num){ timesTwo.push(num * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('jQuery.each()', function() {
|
||||
var timesTwo = [];
|
||||
jQuery.each(numbers, function(){ timesTwo.push(this * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('_.map()', function() {
|
||||
return _.map(objects, function(obj){ return obj.num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('jQuery.map()', function() {
|
||||
return jQuery.map(objects, function(obj){ return obj.num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('_.pluck()', function() {
|
||||
return _.pluck(objects, 'num');
|
||||
});
|
||||
|
||||
JSLitmus.test('_.uniq()', function() {
|
||||
return _.uniq(randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.uniq() (sorted)', function() {
|
||||
return _.uniq(numbers, true);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.sortBy()', function() {
|
||||
return _.sortBy(numbers, function(num){ return -num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('_.isEqual()', function() {
|
||||
return _.isEqual(numbers, randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.keys()', function() {
|
||||
return _.keys(objects);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.values()', function() {
|
||||
return _.values(objects);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.intersect()', function() {
|
||||
return _.intersect(numbers, randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.range()', function() {
|
||||
return _.range(1000);
|
||||
});
|
||||
|
||||
})();
|
27
node_modules/piler/node_modules/underscore.string/test/test_underscore/temp.js
generated
vendored
Normal file
27
node_modules/piler/node_modules/underscore.string/test/test_underscore/temp.js
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
(function() {
|
||||
|
||||
var func = function(){};
|
||||
var date = new Date();
|
||||
var str = "a string";
|
||||
var numbers = [];
|
||||
for (var i=0; i<1000; i++) numbers.push(i);
|
||||
var objects = _.map(numbers, function(n){ return {num : n}; });
|
||||
var randomized = _.sortBy(numbers, function(){ return Math.random(); });
|
||||
|
||||
JSLitmus.test('_.isNumber', function() {
|
||||
return _.isNumber(1000)
|
||||
});
|
||||
|
||||
JSLitmus.test('_.newIsNumber', function() {
|
||||
return _.newIsNumber(1000)
|
||||
});
|
||||
|
||||
JSLitmus.test('_.isNumber(NaN)', function() {
|
||||
return _.isNumber(NaN)
|
||||
});
|
||||
|
||||
JSLitmus.test('_.newIsNumber(NaN)', function() {
|
||||
return _.newIsNumber(NaN)
|
||||
});
|
||||
|
||||
})();
|
19
node_modules/piler/node_modules/underscore.string/test/test_underscore/temp_tests.html
generated
vendored
Normal file
19
node_modules/piler/node_modules/underscore.string/test/test_underscore/temp_tests.html
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Underscore Temporary Tests</title>
|
||||
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="vendor/jquery.js"></script>
|
||||
<script type="text/javascript" src="vendor/jslitmus.js"></script>
|
||||
<script type="text/javascript" src="../underscore.js"></script>
|
||||
<script type="text/javascript" src="temp.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="qunit-header">Underscore Temporary Tests</h1>
|
||||
<h2 class="qunit-userAgent">
|
||||
A page for temporary speed tests, used for developing faster implementations
|
||||
of existing Underscore methods.
|
||||
</h2>
|
||||
<br />
|
||||
</body>
|
||||
</html>
|
43
node_modules/piler/node_modules/underscore.string/test/test_underscore/test.html
generated
vendored
Normal file
43
node_modules/piler/node_modules/underscore.string/test/test_underscore/test.html
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Underscore Test Suite</title>
|
||||
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="vendor/jquery.js"></script>
|
||||
<script type="text/javascript" src="vendor/qunit.js"></script>
|
||||
<script type="text/javascript" src="vendor/jslitmus.js"></script>
|
||||
<script type="text/javascript" src="../underscore.js"></script>
|
||||
<script type="text/javascript" src="../../lib/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="collections.js"></script>
|
||||
<script type="text/javascript" src="arrays.js"></script>
|
||||
<script type="text/javascript" src="functions.js"></script>
|
||||
<script type="text/javascript" src="objects.js"></script>
|
||||
<script type="text/javascript" src="utility.js"></script>
|
||||
<script type="text/javascript" src="chaining.js"></script>
|
||||
<script type="text/javascript" src="speed.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="underscore-test">
|
||||
<h1 id="qunit-header">Underscore Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<br />
|
||||
<h1 class="qunit-header">Underscore Speed Suite</h1>
|
||||
<p>
|
||||
A representative sample of the functions are benchmarked here, to provide
|
||||
a sense of how fast they might run in different browsers.
|
||||
Each iteration runs on an array of 1000 elements.<br /><br />
|
||||
For example, the 'intersect' test measures the number of times you can
|
||||
find the intersection of two thousand-element arrays in one second.
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<script type="text/html" id="template">
|
||||
<%
|
||||
if (data) { data += 12345; }; %>
|
||||
<li><%= data %></li>
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
155
node_modules/piler/node_modules/underscore.string/test/test_underscore/utility.js
generated
vendored
Normal file
155
node_modules/piler/node_modules/underscore.string/test/test_underscore/utility.js
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Utility");
|
||||
|
||||
test("utility: noConflict", function() {
|
||||
var underscore = _.noConflict();
|
||||
ok(underscore.isUndefined(_), "The '_' variable has been returned to its previous state.");
|
||||
var intersection = underscore.intersect([-1, 0, 1, 2], [1, 2, 3, 4]);
|
||||
equals(intersection.join(', '), '1, 2', 'but the intersection function still works');
|
||||
window._ = underscore;
|
||||
});
|
||||
|
||||
test("utility: identity", function() {
|
||||
var moe = {name : 'moe'};
|
||||
equals(_.identity(moe), moe, 'moe is the same as his identity');
|
||||
});
|
||||
|
||||
test("utility: uniqueId", function() {
|
||||
var ids = [], i = 0;
|
||||
while(i++ < 100) ids.push(_.uniqueId());
|
||||
equals(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||
});
|
||||
|
||||
test("utility: times", function() {
|
||||
var vals = [];
|
||||
_.times(3, function (i) { vals.push(i); });
|
||||
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
|
||||
//
|
||||
vals = [];
|
||||
_(3).times(function (i) { vals.push(i); });
|
||||
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
|
||||
});
|
||||
|
||||
test("utility: mixin", function() {
|
||||
_.mixin({
|
||||
myReverse: function(string) {
|
||||
return string.split('').reverse().join('');
|
||||
}
|
||||
});
|
||||
equals(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');
|
||||
equals(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
||||
});
|
||||
|
||||
test("utility: _.escape", function() {
|
||||
equals(_.escape("Curly & Moe"), "Curly & Moe");
|
||||
equals(_.escape("Curly & Moe"), "Curly &amp; Moe");
|
||||
});
|
||||
|
||||
test("utility: template", function() {
|
||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||
var result = basicTemplate({thing : 'This'});
|
||||
equals(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||
|
||||
var sansSemicolonTemplate = _.template("A <% this %> B");
|
||||
equals(sansSemicolonTemplate(), "A B");
|
||||
|
||||
var backslashTemplate = _.template("<%= thing %> is \\ridanculous");
|
||||
equals(backslashTemplate({thing: 'This'}), "This is \\ridanculous");
|
||||
|
||||
var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>');
|
||||
equals(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
||||
|
||||
var fancyTemplate = _.template("<ul><% \
|
||||
for (key in people) { \
|
||||
%><li><%= people[key] %></li><% } %></ul>");
|
||||
result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
||||
equals(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||
|
||||
var escapedCharsInJavascriptTemplate = _.template("<ul><% _.each(numbers.split('\\n'), function(item) { %><li><%= item %></li><% }) %></ul>");
|
||||
result = escapedCharsInJavascriptTemplate({numbers: "one\ntwo\nthree\nfour"});
|
||||
equals(result, "<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>", 'Can use escaped characters (e.g. \\n) in Javascript');
|
||||
|
||||
var namespaceCollisionTemplate = _.template("<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class=\"thumbnail\" rel=\"<%= p %>\"></div><% }); %>");
|
||||
result = namespaceCollisionTemplate({
|
||||
pageCount: 3,
|
||||
thumbnails: {
|
||||
1: "p1-thumbnail.gif",
|
||||
2: "p2-thumbnail.gif",
|
||||
3: "p3-thumbnail.gif"
|
||||
}
|
||||
});
|
||||
equals(result, "3 p3-thumbnail.gif <div class=\"thumbnail\" rel=\"p1-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p2-thumbnail.gif\"></div><div class=\"thumbnail\" rel=\"p3-thumbnail.gif\"></div>");
|
||||
|
||||
var noInterpolateTemplate = _.template("<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
|
||||
result = noInterpolateTemplate();
|
||||
equals(result, "<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>");
|
||||
|
||||
var quoteTemplate = _.template("It's its, not it's");
|
||||
equals(quoteTemplate({}), "It's its, not it's");
|
||||
|
||||
var quoteInStatementAndBody = _.template("<%\
|
||||
if(foo == 'bar'){ \
|
||||
%>Statement quotes and 'quotes'.<% } %>");
|
||||
equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
|
||||
var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.');
|
||||
equals(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.');
|
||||
|
||||
var template = _.template("<i><%- value %></i>");
|
||||
var result = template({value: "<script>"});
|
||||
equals(result, '<i><script></i>');
|
||||
|
||||
var stooge = {
|
||||
name: "Moe",
|
||||
template: _.template("I'm <%= this.name %>")
|
||||
};
|
||||
equals(stooge.template(), "I'm Moe");
|
||||
|
||||
if (!$.browser.msie) {
|
||||
var fromHTML = _.template($('#template').html());
|
||||
equals(fromHTML({data : 12345}).replace(/\s/g, ''), '<li>24690</li>');
|
||||
}
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate : /\{\{([\s\S]+?)\}\}/g,
|
||||
interpolate : /\{\{=([\s\S]+?)\}\}/g
|
||||
};
|
||||
|
||||
var custom = _.template("<ul>{{ for (key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
|
||||
result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
||||
equals(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||
|
||||
var customQuote = _.template("It's its, not it's");
|
||||
equals(customQuote({}), "It's its, not it's");
|
||||
|
||||
var quoteInStatementAndBody = _.template("{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}");
|
||||
equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
evaluate : /<\?([\s\S]+?)\?>/g,
|
||||
interpolate : /<\?=([\s\S]+?)\?>/g
|
||||
};
|
||||
|
||||
var customWithSpecialChars = _.template("<ul><? for (key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
|
||||
result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
||||
equals(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||
|
||||
var customWithSpecialCharsQuote = _.template("It's its, not it's");
|
||||
equals(customWithSpecialCharsQuote({}), "It's its, not it's");
|
||||
|
||||
var quoteInStatementAndBody = _.template("<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>");
|
||||
equals(quoteInStatementAndBody({foo: "bar"}), "Statement quotes and 'quotes'.");
|
||||
|
||||
_.templateSettings = {
|
||||
interpolate : /\{\{(.+?)\}\}/g
|
||||
};
|
||||
|
||||
var mustache = _.template("Hello {{planet}}!");
|
||||
equals(mustache({planet : "World"}), "Hello World!", "can mimic mustache.js");
|
||||
|
||||
var templateWithNull = _.template("a null undefined {{planet}}");
|
||||
equals(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
|
||||
});
|
||||
|
||||
});
|
19
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jquery.js
generated
vendored
Normal file
19
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jquery.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
670
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jslitmus.js
generated
vendored
Normal file
670
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/jslitmus.js
generated
vendored
Normal file
@ -0,0 +1,670 @@
|
||||
// JSLitmus.js
|
||||
//
|
||||
// History:
|
||||
// 2008-10-27: Initial release
|
||||
// 2008-11-09: Account for iteration loop overhead
|
||||
// 2008-11-13: Added OS detection
|
||||
// 2009-02-25: Create tinyURL automatically, shift-click runs tests in reverse
|
||||
//
|
||||
// Copyright (c) 2008-2009, Robert Kieffer
|
||||
// All Rights Reserved
|
||||
//
|
||||
// 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 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.
|
||||
|
||||
(function() {
|
||||
// Private methods and state
|
||||
|
||||
// Get platform info but don't go crazy trying to recognize everything
|
||||
// that's out there. This is just for the major platforms and OSes.
|
||||
var platform = 'unknown platform', ua = navigator.userAgent;
|
||||
|
||||
// Detect OS
|
||||
var oses = ['Windows','iPhone OS','(Intel |PPC )?Mac OS X','Linux'].join('|');
|
||||
var pOS = new RegExp('((' + oses + ') [^ \);]*)').test(ua) ? RegExp.$1 : null;
|
||||
if (!pOS) pOS = new RegExp('((' + oses + ')[^ \);]*)').test(ua) ? RegExp.$1 : null;
|
||||
|
||||
// Detect browser
|
||||
var pName = /(Chrome|MSIE|Safari|Opera|Firefox)/.test(ua) ? RegExp.$1 : null;
|
||||
|
||||
// Detect version
|
||||
var vre = new RegExp('(Version|' + pName + ')[ \/]([^ ;]*)');
|
||||
var pVersion = (pName && vre.test(ua)) ? RegExp.$2 : null;
|
||||
var platform = (pOS && pName && pVersion) ? pName + ' ' + pVersion + ' on ' + pOS : 'unknown platform';
|
||||
|
||||
/**
|
||||
* A smattering of methods that are needed to implement the JSLitmus testbed.
|
||||
*/
|
||||
var jsl = {
|
||||
/**
|
||||
* Enhanced version of escape()
|
||||
*/
|
||||
escape: function(s) {
|
||||
s = s.replace(/,/g, '\\,');
|
||||
s = escape(s);
|
||||
s = s.replace(/\+/g, '%2b');
|
||||
s = s.replace(/ /g, '+');
|
||||
return s;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an element by ID.
|
||||
*/
|
||||
$: function(id) {
|
||||
return document.getElementById(id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Null function
|
||||
*/
|
||||
F: function() {},
|
||||
|
||||
/**
|
||||
* Set the status shown in the UI
|
||||
*/
|
||||
status: function(msg) {
|
||||
var el = jsl.$('jsl_status');
|
||||
if (el) el.innerHTML = msg || '';
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a number to an abbreviated string like, "15K" or "10M"
|
||||
*/
|
||||
toLabel: function(n) {
|
||||
if (n == Infinity) {
|
||||
return 'Infinity';
|
||||
} else if (n > 1e9) {
|
||||
n = Math.round(n/1e8);
|
||||
return n/10 + 'B';
|
||||
} else if (n > 1e6) {
|
||||
n = Math.round(n/1e5);
|
||||
return n/10 + 'M';
|
||||
} else if (n > 1e3) {
|
||||
n = Math.round(n/1e2);
|
||||
return n/10 + 'K';
|
||||
}
|
||||
return n;
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy properties from src to dst
|
||||
*/
|
||||
extend: function(dst, src) {
|
||||
for (var k in src) dst[k] = src[k]; return dst;
|
||||
},
|
||||
|
||||
/**
|
||||
* Like Array.join(), but for the key-value pairs in an object
|
||||
*/
|
||||
join: function(o, delimit1, delimit2) {
|
||||
if (o.join) return o.join(delimit1); // If it's an array
|
||||
var pairs = [];
|
||||
for (var k in o) pairs.push(k + delimit1 + o[k]);
|
||||
return pairs.join(delimit2);
|
||||
},
|
||||
|
||||
/**
|
||||
* Array#indexOf isn't supported in IE, so we use this as a cross-browser solution
|
||||
*/
|
||||
indexOf: function(arr, o) {
|
||||
if (arr.indexOf) return arr.indexOf(o);
|
||||
for (var i = 0; i < this.length; i++) if (arr[i] === o) return i;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test manages a single test (created with
|
||||
* JSLitmus.test())
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
var Test = function (name, f) {
|
||||
if (!f) throw new Error('Undefined test function');
|
||||
if (!(/function[^\(]*\(([^,\)]*)/).test(f.toString())) {
|
||||
throw new Error('"' + name + '" test: Test is not a valid Function object');
|
||||
}
|
||||
this.loopArg = RegExp.$1;
|
||||
this.name = name;
|
||||
this.f = f;
|
||||
};
|
||||
|
||||
jsl.extend(Test, /** @lends Test */ {
|
||||
/** Calibration tests for establishing iteration loop overhead */
|
||||
CALIBRATIONS: [
|
||||
new Test('calibrating loop', function(count) {while (count--);}),
|
||||
new Test('calibrating function', jsl.F)
|
||||
],
|
||||
|
||||
/**
|
||||
* Run calibration tests. Returns true if calibrations are not yet
|
||||
* complete (in which case calling code should run the tests yet again).
|
||||
* onCalibrated - Callback to invoke when calibrations have finished
|
||||
*/
|
||||
calibrate: function(onCalibrated) {
|
||||
for (var i = 0; i < Test.CALIBRATIONS.length; i++) {
|
||||
var cal = Test.CALIBRATIONS[i];
|
||||
if (cal.running) return true;
|
||||
if (!cal.count) {
|
||||
cal.isCalibration = true;
|
||||
cal.onStop = onCalibrated;
|
||||
//cal.MIN_TIME = .1; // Do calibrations quickly
|
||||
cal.run(2e4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jsl.extend(Test.prototype, {/** @lends Test.prototype */
|
||||
/** Initial number of iterations */
|
||||
INIT_COUNT: 10,
|
||||
/** Max iterations allowed (i.e. used to detect bad looping functions) */
|
||||
MAX_COUNT: 1e9,
|
||||
/** Minimum time a test should take to get valid results (secs) */
|
||||
MIN_TIME: .5,
|
||||
|
||||
/** Callback invoked when test state changes */
|
||||
onChange: jsl.F,
|
||||
|
||||
/** Callback invoked when test is finished */
|
||||
onStop: jsl.F,
|
||||
|
||||
/**
|
||||
* Reset test state
|
||||
*/
|
||||
reset: function() {
|
||||
delete this.count;
|
||||
delete this.time;
|
||||
delete this.running;
|
||||
delete this.error;
|
||||
},
|
||||
|
||||
/**
|
||||
* Run the test (in a timeout). We use a timeout to make sure the browser
|
||||
* has a chance to finish rendering any UI changes we've made, like
|
||||
* updating the status message.
|
||||
*/
|
||||
run: function(count) {
|
||||
count = count || this.INIT_COUNT;
|
||||
jsl.status(this.name + ' x ' + count);
|
||||
this.running = true;
|
||||
var me = this;
|
||||
setTimeout(function() {me._run(count);}, 200);
|
||||
},
|
||||
|
||||
/**
|
||||
* The nuts and bolts code that actually runs a test
|
||||
*/
|
||||
_run: function(count) {
|
||||
var me = this;
|
||||
|
||||
// Make sure calibration tests have run
|
||||
if (!me.isCalibration && Test.calibrate(function() {me.run(count);})) return;
|
||||
this.error = null;
|
||||
|
||||
try {
|
||||
var start, f = this.f, now, i = count;
|
||||
|
||||
// Start the timer
|
||||
start = new Date();
|
||||
|
||||
// Now for the money shot. If this is a looping function ...
|
||||
if (this.loopArg) {
|
||||
// ... let it do the iteration itself
|
||||
f(count);
|
||||
} else {
|
||||
// ... otherwise do the iteration for it
|
||||
while (i--) f();
|
||||
}
|
||||
|
||||
// Get time test took (in secs)
|
||||
this.time = Math.max(1,new Date() - start)/1000;
|
||||
|
||||
// Store iteration count and per-operation time taken
|
||||
this.count = count;
|
||||
this.period = this.time/count;
|
||||
|
||||
// Do we need to do another run?
|
||||
this.running = this.time <= this.MIN_TIME;
|
||||
|
||||
// ... if so, compute how many times we should iterate
|
||||
if (this.running) {
|
||||
// Bump the count to the nearest power of 2
|
||||
var x = this.MIN_TIME/this.time;
|
||||
var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2))));
|
||||
count *= pow;
|
||||
if (count > this.MAX_COUNT) {
|
||||
throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Exceptions are caught and displayed in the test UI
|
||||
this.reset();
|
||||
this.error = e;
|
||||
}
|
||||
|
||||
// Figure out what to do next
|
||||
if (this.running) {
|
||||
me.run(count);
|
||||
} else {
|
||||
jsl.status('');
|
||||
me.onStop(me);
|
||||
}
|
||||
|
||||
// Finish up
|
||||
this.onChange(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of operations per second for this test.
|
||||
*
|
||||
* @param normalize if true, iteration loop overhead taken into account
|
||||
*/
|
||||
getHz: function(/**Boolean*/ normalize) {
|
||||
var p = this.period;
|
||||
|
||||
// Adjust period based on the calibration test time
|
||||
if (normalize && !this.isCalibration) {
|
||||
var cal = Test.CALIBRATIONS[this.loopArg ? 0 : 1];
|
||||
|
||||
// If the period is within 20% of the calibration time, then zero the
|
||||
// it out
|
||||
p = p < cal.period*1.2 ? 0 : p - cal.period;
|
||||
}
|
||||
|
||||
return Math.round(1/p);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a friendly string describing the test
|
||||
*/
|
||||
toString: function() {
|
||||
return this.name + ' - ' + this.time/this.count + ' secs';
|
||||
}
|
||||
});
|
||||
|
||||
// CSS we need for the UI
|
||||
var STYLESHEET = '<style> \
|
||||
#jslitmus {font-family:sans-serif; font-size: 12px;} \
|
||||
#jslitmus a {text-decoration: none;} \
|
||||
#jslitmus a:hover {text-decoration: underline;} \
|
||||
#jsl_status { \
|
||||
margin-top: 10px; \
|
||||
font-size: 10px; \
|
||||
color: #888; \
|
||||
} \
|
||||
A IMG {border:none} \
|
||||
#test_results { \
|
||||
margin-top: 10px; \
|
||||
font-size: 12px; \
|
||||
font-family: sans-serif; \
|
||||
border-collapse: collapse; \
|
||||
border-spacing: 0px; \
|
||||
} \
|
||||
#test_results th, #test_results td { \
|
||||
border: solid 1px #ccc; \
|
||||
vertical-align: top; \
|
||||
padding: 3px; \
|
||||
} \
|
||||
#test_results th { \
|
||||
vertical-align: bottom; \
|
||||
background-color: #ccc; \
|
||||
padding: 1px; \
|
||||
font-size: 10px; \
|
||||
} \
|
||||
#test_results #test_platform { \
|
||||
color: #444; \
|
||||
text-align:center; \
|
||||
} \
|
||||
#test_results .test_row { \
|
||||
color: #006; \
|
||||
cursor: pointer; \
|
||||
} \
|
||||
#test_results .test_nonlooping { \
|
||||
border-left-style: dotted; \
|
||||
border-left-width: 2px; \
|
||||
} \
|
||||
#test_results .test_looping { \
|
||||
border-left-style: solid; \
|
||||
border-left-width: 2px; \
|
||||
} \
|
||||
#test_results .test_name {white-space: nowrap;} \
|
||||
#test_results .test_pending { \
|
||||
} \
|
||||
#test_results .test_running { \
|
||||
font-style: italic; \
|
||||
} \
|
||||
#test_results .test_done {} \
|
||||
#test_results .test_done { \
|
||||
text-align: right; \
|
||||
font-family: monospace; \
|
||||
} \
|
||||
#test_results .test_error {color: #600;} \
|
||||
#test_results .test_error .error_head {font-weight:bold;} \
|
||||
#test_results .test_error .error_body {font-size:85%;} \
|
||||
#test_results .test_row:hover td { \
|
||||
background-color: #ffc; \
|
||||
text-decoration: underline; \
|
||||
} \
|
||||
#chart { \
|
||||
margin: 10px 0px; \
|
||||
width: 250px; \
|
||||
} \
|
||||
#chart img { \
|
||||
border: solid 1px #ccc; \
|
||||
margin-bottom: 5px; \
|
||||
} \
|
||||
#chart #tiny_url { \
|
||||
height: 40px; \
|
||||
width: 250px; \
|
||||
} \
|
||||
#jslitmus_credit { \
|
||||
font-size: 10px; \
|
||||
color: #888; \
|
||||
margin-top: 8px; \
|
||||
} \
|
||||
</style>';
|
||||
|
||||
// HTML markup for the UI
|
||||
var MARKUP = '<div id="jslitmus"> \
|
||||
<button onclick="JSLitmus.runAll(event)">Run Tests</button> \
|
||||
<button id="stop_button" disabled="disabled" onclick="JSLitmus.stop()">Stop Tests</button> \
|
||||
<br \> \
|
||||
<br \> \
|
||||
<input type="checkbox" style="vertical-align: middle" id="test_normalize" checked="checked" onchange="JSLitmus.renderAll()""> Normalize results \
|
||||
<table id="test_results"> \
|
||||
<colgroup> \
|
||||
<col /> \
|
||||
<col width="100" /> \
|
||||
</colgroup> \
|
||||
<tr><th id="test_platform" colspan="2">' + platform + '</th></tr> \
|
||||
<tr><th>Test</th><th>Ops/sec</th></tr> \
|
||||
<tr id="test_row_template" class="test_row" style="display:none"> \
|
||||
<td class="test_name"></td> \
|
||||
<td class="test_result">Ready</td> \
|
||||
</tr> \
|
||||
</table> \
|
||||
<div id="jsl_status"></div> \
|
||||
<div id="chart" style="display:none"> \
|
||||
<a id="chart_link" target="_blank"><img id="chart_image"></a> \
|
||||
TinyURL (for chart): \
|
||||
<iframe id="tiny_url" frameBorder="0" scrolling="no" src=""></iframe> \
|
||||
</div> \
|
||||
<a id="jslitmus_credit" title="JSLitmus home page" href="http://code.google.com/p/jslitmus" target="_blank">Powered by JSLitmus</a> \
|
||||
</div>';
|
||||
|
||||
/**
|
||||
* The public API for creating and running tests
|
||||
*/
|
||||
window.JSLitmus = {
|
||||
/** The list of all tests that have been registered with JSLitmus.test */
|
||||
_tests: [],
|
||||
/** The queue of tests that need to be run */
|
||||
_queue: [],
|
||||
|
||||
/**
|
||||
* The parsed query parameters the current page URL. This is provided as a
|
||||
* convenience for test functions - it's not used by JSLitmus proper
|
||||
*/
|
||||
params: {},
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
_init: function() {
|
||||
// Parse query params into JSLitmus.params[] hash
|
||||
var match = (location + '').match(/([^?#]*)(#.*)?$/);
|
||||
if (match) {
|
||||
var pairs = match[1].split('&');
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
var pair = pairs[i].split('=');
|
||||
if (pair.length > 1) {
|
||||
var key = pair.shift();
|
||||
var value = pair.length > 1 ? pair.join('=') : pair[0];
|
||||
this.params[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the stylesheet. We have to do this here because IE
|
||||
// doesn't honor sheets written after the document has loaded.
|
||||
document.write(STYLESHEET);
|
||||
|
||||
// Setup the rest of the UI once the document is loaded
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('load', this._setup, false);
|
||||
} else if (document.addEventListener) {
|
||||
document.addEventListener('load', this._setup, false);
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent('onload', this._setup);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the UI
|
||||
*/
|
||||
_setup: function() {
|
||||
var el = jsl.$('jslitmus_container');
|
||||
if (!el) document.body.appendChild(el = document.createElement('div'));
|
||||
|
||||
el.innerHTML = MARKUP;
|
||||
|
||||
// Render the UI for all our tests
|
||||
for (var i=0; i < JSLitmus._tests.length; i++)
|
||||
JSLitmus.renderTest(JSLitmus._tests[i]);
|
||||
},
|
||||
|
||||
/**
|
||||
* (Re)render all the test results
|
||||
*/
|
||||
renderAll: function() {
|
||||
for (var i = 0; i < JSLitmus._tests.length; i++)
|
||||
JSLitmus.renderTest(JSLitmus._tests[i]);
|
||||
JSLitmus.renderChart();
|
||||
},
|
||||
|
||||
/**
|
||||
* (Re)render the chart graphics
|
||||
*/
|
||||
renderChart: function() {
|
||||
var url = JSLitmus.chartUrl();
|
||||
jsl.$('chart_link').href = url;
|
||||
jsl.$('chart_image').src = url;
|
||||
jsl.$('chart').style.display = '';
|
||||
|
||||
// Update the tiny URL
|
||||
jsl.$('tiny_url').src = 'http://tinyurl.com/api-create.php?url='+escape(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* (Re)render the results for a specific test
|
||||
*/
|
||||
renderTest: function(test) {
|
||||
// Make a new row if needed
|
||||
if (!test._row) {
|
||||
var trow = jsl.$('test_row_template');
|
||||
if (!trow) return;
|
||||
|
||||
test._row = trow.cloneNode(true);
|
||||
test._row.style.display = '';
|
||||
test._row.id = '';
|
||||
test._row.onclick = function() {JSLitmus._queueTest(test);};
|
||||
test._row.title = 'Run ' + test.name + ' test';
|
||||
trow.parentNode.appendChild(test._row);
|
||||
test._row.cells[0].innerHTML = test.name;
|
||||
}
|
||||
|
||||
var cell = test._row.cells[1];
|
||||
var cns = [test.loopArg ? 'test_looping' : 'test_nonlooping'];
|
||||
|
||||
if (test.error) {
|
||||
cns.push('test_error');
|
||||
cell.innerHTML =
|
||||
'<div class="error_head">' + test.error + '</div>' +
|
||||
'<ul class="error_body"><li>' +
|
||||
jsl.join(test.error, ': ', '</li><li>') +
|
||||
'</li></ul>';
|
||||
} else {
|
||||
if (test.running) {
|
||||
cns.push('test_running');
|
||||
cell.innerHTML = 'running';
|
||||
} else if (jsl.indexOf(JSLitmus._queue, test) >= 0) {
|
||||
cns.push('test_pending');
|
||||
cell.innerHTML = 'pending';
|
||||
} else if (test.count) {
|
||||
cns.push('test_done');
|
||||
var hz = test.getHz(jsl.$('test_normalize').checked);
|
||||
cell.innerHTML = hz != Infinity ? hz : '∞';
|
||||
} else {
|
||||
cell.innerHTML = 'ready';
|
||||
}
|
||||
}
|
||||
cell.className = cns.join(' ');
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new test
|
||||
*/
|
||||
test: function(name, f) {
|
||||
// Create the Test object
|
||||
var test = new Test(name, f);
|
||||
JSLitmus._tests.push(test);
|
||||
|
||||
// Re-render if the test state changes
|
||||
test.onChange = JSLitmus.renderTest;
|
||||
|
||||
// Run the next test if this one finished
|
||||
test.onStop = function(test) {
|
||||
if (JSLitmus.onTestFinish) JSLitmus.onTestFinish(test);
|
||||
JSLitmus.currentTest = null;
|
||||
JSLitmus._nextTest();
|
||||
};
|
||||
|
||||
// Render the new test
|
||||
this.renderTest(test);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add all tests to the run queue
|
||||
*/
|
||||
runAll: function(e) {
|
||||
e = e || window.event;
|
||||
var reverse = e && e.shiftKey, len = JSLitmus._tests.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
JSLitmus._queueTest(JSLitmus._tests[!reverse ? i : (len - i - 1)]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all tests from the run queue. The current test has to finish on
|
||||
* it's own though
|
||||
*/
|
||||
stop: function() {
|
||||
while (JSLitmus._queue.length) {
|
||||
var test = JSLitmus._queue.shift();
|
||||
JSLitmus.renderTest(test);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Run the next test in the run queue
|
||||
*/
|
||||
_nextTest: function() {
|
||||
if (!JSLitmus.currentTest) {
|
||||
var test = JSLitmus._queue.shift();
|
||||
if (test) {
|
||||
jsl.$('stop_button').disabled = false;
|
||||
JSLitmus.currentTest = test;
|
||||
test.run();
|
||||
JSLitmus.renderTest(test);
|
||||
if (JSLitmus.onTestStart) JSLitmus.onTestStart(test);
|
||||
} else {
|
||||
jsl.$('stop_button').disabled = true;
|
||||
JSLitmus.renderChart();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a test to the run queue
|
||||
*/
|
||||
_queueTest: function(test) {
|
||||
if (jsl.indexOf(JSLitmus._queue, test) >= 0) return;
|
||||
JSLitmus._queue.push(test);
|
||||
JSLitmus.renderTest(test);
|
||||
JSLitmus._nextTest();
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a Google Chart URL that shows the data for all tests
|
||||
*/
|
||||
chartUrl: function() {
|
||||
var n = JSLitmus._tests.length, markers = [], data = [];
|
||||
var d, min = 0, max = -1e10;
|
||||
var normalize = jsl.$('test_normalize').checked;
|
||||
|
||||
// Gather test data
|
||||
for (var i=0; i < JSLitmus._tests.length; i++) {
|
||||
var test = JSLitmus._tests[i];
|
||||
if (test.count) {
|
||||
var hz = test.getHz(normalize);
|
||||
var v = hz != Infinity ? hz : 0;
|
||||
data.push(v);
|
||||
markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
|
||||
markers.length + ',10');
|
||||
max = Math.max(v, max);
|
||||
}
|
||||
}
|
||||
if (markers.length <= 0) return null;
|
||||
|
||||
// Build chart title
|
||||
var title = document.getElementsByTagName('title');
|
||||
title = (title && title.length) ? title[0].innerHTML : null;
|
||||
var chart_title = [];
|
||||
if (title) chart_title.push(title);
|
||||
chart_title.push('Ops/sec (' + platform + ')');
|
||||
|
||||
// Build labels
|
||||
var labels = [jsl.toLabel(min), jsl.toLabel(max)];
|
||||
|
||||
var w = 250, bw = 15;
|
||||
var bs = 5;
|
||||
var h = markers.length*(bw + bs) + 30 + chart_title.length*20;
|
||||
|
||||
var params = {
|
||||
chtt: escape(chart_title.join('|')),
|
||||
chts: '000000,10',
|
||||
cht: 'bhg', // chart type
|
||||
chd: 't:' + data.join(','), // data set
|
||||
chds: min + ',' + max, // max/min of data
|
||||
chxt: 'x', // label axes
|
||||
chxl: '0:|' + labels.join('|'), // labels
|
||||
chsp: '0,1',
|
||||
chm: markers.join('|'), // test names
|
||||
chbh: [bw, 0, bs].join(','), // bar widths
|
||||
// chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
|
||||
chs: w + 'x' + h
|
||||
};
|
||||
return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
|
||||
}
|
||||
};
|
||||
|
||||
JSLitmus._init();
|
||||
})();
|
196
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css
generated
vendored
Normal file
196
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.css
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, .qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header */
|
||||
|
||||
#qunit-header, .qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 15px 15px 0 0;
|
||||
-moz-border-radius: 15px 15px 0 0;
|
||||
-webkit-border-top-right-radius: 15px;
|
||||
-webkit-border-top-left-radius: 15px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0em 0 0.5em 2em;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2b81af;
|
||||
color: #fff;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #fff;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests ol {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
-webkit-border-radius: 15px;
|
||||
|
||||
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 {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
margin: 0.5em;
|
||||
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #5E740B;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #EE5757;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: green; }
|
||||
|
||||
#qunit-banner.qunit-fail,
|
||||
#qunit-testrunner-toolbar { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Footer */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
color: #2b81af;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-radius: 0 0 15px 15px;
|
||||
-moz-border-radius: 0 0 15px 15px;
|
||||
-webkit-border-bottom-right-radius: 15px;
|
||||
-webkit-border-bottom-left-radius: 15px;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
}
|
2360
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js
generated
vendored
Normal file
2360
node_modules/piler/node_modules/underscore.string/test/test_underscore/vendor/qunit.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
999
node_modules/piler/node_modules/underscore.string/test/underscore.js
generated
vendored
Normal file
999
node_modules/piler/node_modules/underscore.string/test/underscore.js
generated
vendored
Normal file
@ -0,0 +1,999 @@
|
||||
// Underscore.js 1.3.1
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable 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() {
|
||||
|
||||
// Baseline setup
|
||||
// --------------
|
||||
|
||||
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||
var root = this;
|
||||
|
||||
// Save the previous value of the `_` variable.
|
||||
var previousUnderscore = root._;
|
||||
|
||||
// Establish the object that gets returned to break out of a loop iteration.
|
||||
var breaker = {};
|
||||
|
||||
// Save bytes in the minified (but not gzipped) version:
|
||||
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||||
|
||||
// Create quick reference variables for speed access to core prototypes.
|
||||
var slice = ArrayProto.slice,
|
||||
unshift = ArrayProto.unshift,
|
||||
toString = ObjProto.toString,
|
||||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||
|
||||
// All **ECMAScript 5** native function implementations that we hope to use
|
||||
// are declared here.
|
||||
var
|
||||
nativeForEach = ArrayProto.forEach,
|
||||
nativeMap = ArrayProto.map,
|
||||
nativeReduce = ArrayProto.reduce,
|
||||
nativeReduceRight = ArrayProto.reduceRight,
|
||||
nativeFilter = ArrayProto.filter,
|
||||
nativeEvery = ArrayProto.every,
|
||||
nativeSome = ArrayProto.some,
|
||||
nativeIndexOf = ArrayProto.indexOf,
|
||||
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||||
nativeIsArray = Array.isArray,
|
||||
nativeKeys = Object.keys,
|
||||
nativeBind = FuncProto.bind;
|
||||
|
||||
// Create a safe reference to the Underscore object for use below.
|
||||
var _ = function(obj) { return new wrapper(obj); };
|
||||
|
||||
// Export the Underscore object for **Node.js**, with
|
||||
// backwards-compatibility for the old `require()` API. If we're in
|
||||
// the browser, add `_` as a global object via a string identifier,
|
||||
// for Closure Compiler "advanced" mode.
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
exports = module.exports = _;
|
||||
}
|
||||
exports._ = _;
|
||||
} else {
|
||||
root['_'] = _;
|
||||
}
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '1.3.1';
|
||||
|
||||
// Collection Functions
|
||||
// --------------------
|
||||
|
||||
// The cornerstone, an `each` implementation, aka `forEach`.
|
||||
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||
if (obj == null) return;
|
||||
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (obj.length === +obj.length) {
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
|
||||
}
|
||||
} else {
|
||||
for (var key in obj) {
|
||||
if (_.has(obj, key)) {
|
||||
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Return the results of applying the iterator to each element.
|
||||
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||
_.map = _.collect = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
results[results.length] = iterator.call(context, value, index, list);
|
||||
});
|
||||
if (obj.length === +obj.length) results.length = obj.length;
|
||||
return results;
|
||||
};
|
||||
|
||||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||
var initial = arguments.length > 2;
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||
}
|
||||
each(obj, function(value, index, list) {
|
||||
if (!initial) {
|
||||
memo = value;
|
||||
initial = true;
|
||||
} else {
|
||||
memo = iterator.call(context, memo, value, index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||
return memo;
|
||||
};
|
||||
|
||||
// The right-associative version of reduce, also known as `foldr`.
|
||||
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||
var initial = arguments.length > 2;
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
}
|
||||
var reversed = _.toArray(obj).reverse();
|
||||
if (context && !initial) iterator = _.bind(iterator, context);
|
||||
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
||||
};
|
||||
|
||||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||
_.find = _.detect = function(obj, iterator, context) {
|
||||
var result;
|
||||
any(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) {
|
||||
result = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Return all the elements that pass a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||
// Aliased as `select`.
|
||||
_.filter = _.select = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
each(obj, function(value, index, list) {
|
||||
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||
// Aliased as `all`.
|
||||
_.every = _.all = function(obj, iterator, context) {
|
||||
var result = true;
|
||||
if (obj == null) return result;
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Determine if at least one element in the object matches a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||
// Aliased as `any`.
|
||||
var any = _.some = _.any = function(obj, iterator, context) {
|
||||
iterator || (iterator = _.identity);
|
||||
var result = false;
|
||||
if (obj == null) return result;
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return !!result;
|
||||
};
|
||||
|
||||
// Determine if a given value is included in the array or object using `===`.
|
||||
// Aliased as `contains`.
|
||||
_.include = _.contains = function(obj, target) {
|
||||
var found = false;
|
||||
if (obj == null) return found;
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
found = any(obj, function(value) {
|
||||
return value === target;
|
||||
});
|
||||
return found;
|
||||
};
|
||||
|
||||
// Invoke a method (with arguments) on every item in a collection.
|
||||
_.invoke = function(obj, method) {
|
||||
var args = slice.call(arguments, 2);
|
||||
return _.map(obj, function(value) {
|
||||
return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
|
||||
});
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `map`: fetching a property.
|
||||
_.pluck = function(obj, key) {
|
||||
return _.map(obj, function(value){ return value[key]; });
|
||||
};
|
||||
|
||||
// Return the maximum element or (element-based computation).
|
||||
_.max = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||
var result = {computed : -Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed >= result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Return the minimum element (or element-based computation).
|
||||
_.min = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||
var result = {computed : Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed < result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Shuffle an array.
|
||||
_.shuffle = function(obj) {
|
||||
var shuffled = [], rand;
|
||||
each(obj, function(value, index, list) {
|
||||
if (index == 0) {
|
||||
shuffled[0] = value;
|
||||
} else {
|
||||
rand = Math.floor(Math.random() * (index + 1));
|
||||
shuffled[index] = shuffled[rand];
|
||||
shuffled[rand] = value;
|
||||
}
|
||||
});
|
||||
return shuffled;
|
||||
};
|
||||
|
||||
// Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = function(obj, iterator, context) {
|
||||
return _.pluck(_.map(obj, function(value, index, list) {
|
||||
return {
|
||||
value : value,
|
||||
criteria : iterator.call(context, value, index, list)
|
||||
};
|
||||
}).sort(function(left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}), 'value');
|
||||
};
|
||||
|
||||
// Groups the object's values by a criterion. Pass either a string attribute
|
||||
// to group by, or a function that returns the criterion.
|
||||
_.groupBy = function(obj, val) {
|
||||
var result = {};
|
||||
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);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Use a comparator function to figure out at what index an object should
|
||||
// be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = function(array, obj, iterator) {
|
||||
iterator || (iterator = _.identity);
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
var mid = (low + high) >> 1;
|
||||
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
// Safely convert anything iterable into a real, live array.
|
||||
_.toArray = function(iterable) {
|
||||
if (!iterable) return [];
|
||||
if (iterable.toArray) return iterable.toArray();
|
||||
if (_.isArray(iterable)) return slice.call(iterable);
|
||||
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||
return _.values(iterable);
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
_.size = function(obj) {
|
||||
return _.toArray(obj).length;
|
||||
};
|
||||
|
||||
// Array Functions
|
||||
// ---------------
|
||||
|
||||
// Get the first element of an array. Passing **n** will return the first N
|
||||
// values in the array. Aliased as `head`. The **guard** check allows it to work
|
||||
// with `_.map`.
|
||||
_.first = _.head = function(array, n, guard) {
|
||||
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||
};
|
||||
|
||||
// Returns everything but the last entry of the array. Especcialy useful on
|
||||
// the arguments object. Passing **n** will return all the values in
|
||||
// the array, excluding the last N. The **guard** check allows it to work with
|
||||
// `_.map`.
|
||||
_.initial = function(array, n, guard) {
|
||||
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
|
||||
};
|
||||
|
||||
// Get the last element of an array. Passing **n** will return the last N
|
||||
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||
_.last = function(array, n, guard) {
|
||||
if ((n != null) && !guard) {
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
} else {
|
||||
return array[array.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
// Returns everything but the first entry of the array. Aliased as `tail`.
|
||||
// Especially useful on the arguments object. Passing an **index** will return
|
||||
// the rest of the values in the array from that index onward. The **guard**
|
||||
// check allows it to work with `_.map`.
|
||||
_.rest = _.tail = function(array, index, guard) {
|
||||
return slice.call(array, (index == null) || guard ? 1 : index);
|
||||
};
|
||||
|
||||
// Trim out all falsy values from an array.
|
||||
_.compact = function(array) {
|
||||
return _.filter(array, function(value){ return !!value; });
|
||||
};
|
||||
|
||||
// Return a completely flattened version of an array.
|
||||
_.flatten = function(array, shallow) {
|
||||
return _.reduce(array, function(memo, value) {
|
||||
if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
|
||||
memo[memo.length] = value;
|
||||
return memo;
|
||||
}, []);
|
||||
};
|
||||
|
||||
// Return a version of the array that does not contain the specified value(s).
|
||||
_.without = function(array) {
|
||||
return _.difference(array, slice.call(arguments, 1));
|
||||
};
|
||||
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
// Aliased as `unique`.
|
||||
_.uniq = _.unique = function(array, isSorted, iterator) {
|
||||
var initial = iterator ? _.map(array, iterator) : array;
|
||||
var result = [];
|
||||
_.reduce(initial, function(memo, el, i) {
|
||||
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
|
||||
memo[memo.length] = el;
|
||||
result[result.length] = array[i];
|
||||
}
|
||||
return memo;
|
||||
}, []);
|
||||
return result;
|
||||
};
|
||||
|
||||
// Produce an array that contains the union: each distinct element from all of
|
||||
// the passed-in arrays.
|
||||
_.union = function() {
|
||||
return _.uniq(_.flatten(arguments, true));
|
||||
};
|
||||
|
||||
// Produce an array that contains every item shared between all the
|
||||
// passed-in arrays. (Aliased as "intersect" for back-compat.)
|
||||
_.intersection = _.intersect = function(array) {
|
||||
var rest = slice.call(arguments, 1);
|
||||
return _.filter(_.uniq(array), function(item) {
|
||||
return _.every(rest, function(other) {
|
||||
return _.indexOf(other, item) >= 0;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Take the difference between one array and a number of other arrays.
|
||||
// Only the elements present in just the first array will remain.
|
||||
_.difference = function(array) {
|
||||
var rest = _.flatten(slice.call(arguments, 1));
|
||||
return _.filter(array, function(value){ return !_.include(rest, value); });
|
||||
};
|
||||
|
||||
// Zip together multiple lists into a single array -- elements that share
|
||||
// an index go together.
|
||||
_.zip = function() {
|
||||
var args = slice.call(arguments);
|
||||
var length = _.max(_.pluck(args, 'length'));
|
||||
var results = new Array(length);
|
||||
for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
|
||||
return results;
|
||||
};
|
||||
|
||||
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||||
// we need this function. Return the position of the first occurrence of an
|
||||
// item in an array, or -1 if the item is not included in the array.
|
||||
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||
// If the array is large and already in sort order, pass `true`
|
||||
// for **isSorted** to use binary search.
|
||||
_.indexOf = function(array, item, isSorted) {
|
||||
if (array == null) return -1;
|
||||
var i, l;
|
||||
if (isSorted) {
|
||||
i = _.sortedIndex(array, item);
|
||||
return array[i] === item ? i : -1;
|
||||
}
|
||||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||
for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
if (array == null) return -1;
|
||||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||
var i = array.length;
|
||||
while (i--) if (i in array && array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Generate an integer Array containing an arithmetic progression. A port of
|
||||
// the native Python `range()` function. See
|
||||
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||||
_.range = function(start, stop, step) {
|
||||
if (arguments.length <= 1) {
|
||||
stop = start || 0;
|
||||
start = 0;
|
||||
}
|
||||
step = arguments[2] || 1;
|
||||
|
||||
var len = Math.max(Math.ceil((stop - start) / step), 0);
|
||||
var idx = 0;
|
||||
var range = new Array(len);
|
||||
|
||||
while(idx < len) {
|
||||
range[idx++] = start;
|
||||
start += step;
|
||||
}
|
||||
|
||||
return range;
|
||||
};
|
||||
|
||||
// Function (ahem) Functions
|
||||
// ------------------
|
||||
|
||||
// Reusable constructor function for prototype setting.
|
||||
var ctor = function(){};
|
||||
|
||||
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||
// optionally). Binding with arguments is also known as `curry`.
|
||||
// Delegates to **ECMAScript 5**'s native `Function.bind` if available.
|
||||
// We check for `func.bind` first, to fail fast when `func` is undefined.
|
||||
_.bind = function bind(func, context) {
|
||||
var bound, args;
|
||||
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||||
if (!_.isFunction(func)) throw new TypeError;
|
||||
args = slice.call(arguments, 2);
|
||||
return bound = function() {
|
||||
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||||
ctor.prototype = func.prototype;
|
||||
var self = new ctor;
|
||||
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||||
if (Object(result) === result) return result;
|
||||
return self;
|
||||
};
|
||||
};
|
||||
|
||||
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||
// all callbacks defined on an object belong to it.
|
||||
_.bindAll = function(obj) {
|
||||
var funcs = slice.call(arguments, 1);
|
||||
if (funcs.length == 0) funcs = _.functions(obj);
|
||||
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Memoize an expensive function by storing its results.
|
||||
_.memoize = function(func, hasher) {
|
||||
var memo = {};
|
||||
hasher || (hasher = _.identity);
|
||||
return function() {
|
||||
var key = hasher.apply(this, arguments);
|
||||
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||||
};
|
||||
};
|
||||
|
||||
// Delays a function for the given number of milliseconds, and then calls
|
||||
// it with the arguments supplied.
|
||||
_.delay = function(func, wait) {
|
||||
var args = slice.call(arguments, 2);
|
||||
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||
};
|
||||
|
||||
// Defers a function, scheduling it to run after the current call stack has
|
||||
// cleared.
|
||||
_.defer = function(func) {
|
||||
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
||||
};
|
||||
|
||||
// Returns a function, that, when invoked, will only be triggered at most once
|
||||
// during a given window of time.
|
||||
_.throttle = function(func, wait) {
|
||||
var context, args, timeout, throttling, more;
|
||||
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||
return function() {
|
||||
context = this; args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (more) func.apply(context, args);
|
||||
whenDone();
|
||||
};
|
||||
if (!timeout) timeout = setTimeout(later, wait);
|
||||
if (throttling) {
|
||||
more = true;
|
||||
} else {
|
||||
func.apply(context, args);
|
||||
}
|
||||
whenDone();
|
||||
throttling = true;
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function, that, as long as it continues to be invoked, will not
|
||||
// be triggered. The function will be called after it stops being called for
|
||||
// N milliseconds.
|
||||
_.debounce = function(func, wait) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
func.apply(context, args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that will be executed at most one time, no matter how
|
||||
// often you call it. Useful for lazy initialization.
|
||||
_.once = function(func) {
|
||||
var ran = false, memo;
|
||||
return function() {
|
||||
if (ran) return memo;
|
||||
ran = true;
|
||||
return memo = func.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns the first function passed as an argument to the second,
|
||||
// allowing you to adjust arguments, run code before and after, and
|
||||
// conditionally execute the original function.
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func].concat(slice.call(arguments, 0));
|
||||
return wrapper.apply(this, args);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that is the composition of a list of functions, each
|
||||
// consuming the return value of the function that follows.
|
||||
_.compose = function() {
|
||||
var funcs = arguments;
|
||||
return function() {
|
||||
var args = arguments;
|
||||
for (var i = funcs.length - 1; i >= 0; i--) {
|
||||
args = [funcs[i].apply(this, args)];
|
||||
}
|
||||
return args[0];
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that will only be executed after being called N times.
|
||||
_.after = function(times, func) {
|
||||
if (times <= 0) return func();
|
||||
return function() {
|
||||
if (--times < 1) { return func.apply(this, arguments); }
|
||||
};
|
||||
};
|
||||
|
||||
// Object Functions
|
||||
// ----------------
|
||||
|
||||
// Retrieve the names of an object's properties.
|
||||
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||
_.keys = nativeKeys || function(obj) {
|
||||
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
||||
var keys = [];
|
||||
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
|
||||
return keys;
|
||||
};
|
||||
|
||||
// Retrieve the values of an object's properties.
|
||||
_.values = function(obj) {
|
||||
return _.map(obj, _.identity);
|
||||
};
|
||||
|
||||
// Return a sorted list of the function names available on the object.
|
||||
// Aliased as `methods`
|
||||
_.functions = _.methods = function(obj) {
|
||||
var names = [];
|
||||
for (var key in obj) {
|
||||
if (_.isFunction(obj[key])) names.push(key);
|
||||
}
|
||||
return names.sort();
|
||||
};
|
||||
|
||||
// Extend a given object with all the properties in passed-in object(s).
|
||||
_.extend = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
obj[prop] = source[prop];
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Fill in a given object with default properties.
|
||||
_.defaults = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
if (obj[prop] == null) obj[prop] = source[prop];
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = function(obj) {
|
||||
if (!_.isObject(obj)) return obj;
|
||||
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||||
};
|
||||
|
||||
// Invokes interceptor with the obj, and then returns obj.
|
||||
// The primary purpose of this method is to "tap into" a method chain, in
|
||||
// order to perform operations on intermediate results within the chain.
|
||||
_.tap = function(obj, interceptor) {
|
||||
interceptor(obj);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Internal recursive comparison function.
|
||||
function eq(a, b, stack) {
|
||||
// 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.
|
||||
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||
// A strict comparison is necessary because `null == undefined`.
|
||||
if (a == null || b == null) return a === b;
|
||||
// Unwrap any wrapped objects.
|
||||
if (a._chain) a = a._wrapped;
|
||||
if (b._chain) b = b._wrapped;
|
||||
// Invoke a custom `isEqual` method if one is provided.
|
||||
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
||||
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
||||
// Compare `[[Class]]` names.
|
||||
var className = toString.call(a);
|
||||
if (className != toString.call(b)) return false;
|
||||
switch (className) {
|
||||
// Strings, numbers, dates, and booleans are compared by value.
|
||||
case '[object String]':
|
||||
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||||
// equivalent to `new String("5")`.
|
||||
return a == String(b);
|
||||
case '[object Number]':
|
||||
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
||||
// other numeric values.
|
||||
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
|
||||
case '[object Date]':
|
||||
case '[object Boolean]':
|
||||
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||||
// millisecond representations. Note that invalid dates with millisecond representations
|
||||
// of `NaN` are not equivalent.
|
||||
return +a == +b;
|
||||
// RegExps are compared by their source patterns and flags.
|
||||
case '[object RegExp]':
|
||||
return a.source == b.source &&
|
||||
a.global == b.global &&
|
||||
a.multiline == b.multiline &&
|
||||
a.ignoreCase == b.ignoreCase;
|
||||
}
|
||||
if (typeof a != 'object' || typeof b != 'object') return false;
|
||||
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||||
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||||
var length = stack.length;
|
||||
while (length--) {
|
||||
// Linear search. Performance is inversely proportional to the number of
|
||||
// unique nested structures.
|
||||
if (stack[length] == a) return true;
|
||||
}
|
||||
// Add the first object to the stack of traversed objects.
|
||||
stack.push(a);
|
||||
var size = 0, result = true;
|
||||
// Recursively compare objects and arrays.
|
||||
if (className == '[object Array]') {
|
||||
// Compare array lengths to determine if a deep comparison is necessary.
|
||||
size = a.length;
|
||||
result = size == b.length;
|
||||
if (result) {
|
||||
// Deep compare the contents, ignoring non-numeric properties.
|
||||
while (size--) {
|
||||
// Ensure commutative equality for sparse arrays.
|
||||
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Objects with different constructors are not equivalent.
|
||||
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
||||
// Deep compare objects.
|
||||
for (var key in a) {
|
||||
if (_.has(a, key)) {
|
||||
// Count the expected number of properties.
|
||||
size++;
|
||||
// Deep compare each member.
|
||||
if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
|
||||
}
|
||||
}
|
||||
// Ensure that both objects contain the same number of properties.
|
||||
if (result) {
|
||||
for (key in b) {
|
||||
if (_.has(b, key) && !(size--)) break;
|
||||
}
|
||||
result = !size;
|
||||
}
|
||||
}
|
||||
// Remove the first object from the stack of traversed objects.
|
||||
stack.pop();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = function(a, b) {
|
||||
return eq(a, b, []);
|
||||
};
|
||||
|
||||
// Is a given array, string, or object empty?
|
||||
// An "empty" object has no enumerable own-properties.
|
||||
_.isEmpty = function(obj) {
|
||||
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||||
for (var key in obj) if (_.has(obj, key)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Is a given value a DOM element?
|
||||
_.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
};
|
||||
|
||||
// Is a given value an array?
|
||||
// Delegates to ECMA5's native Array.isArray
|
||||
_.isArray = nativeIsArray || function(obj) {
|
||||
return toString.call(obj) == '[object Array]';
|
||||
};
|
||||
|
||||
// Is a given variable an object?
|
||||
_.isObject = function(obj) {
|
||||
return obj === Object(obj);
|
||||
};
|
||||
|
||||
// Is a given variable an arguments object?
|
||||
_.isArguments = function(obj) {
|
||||
return toString.call(obj) == '[object Arguments]';
|
||||
};
|
||||
if (!_.isArguments(arguments)) {
|
||||
_.isArguments = function(obj) {
|
||||
return !!(obj && _.has(obj, 'callee'));
|
||||
};
|
||||
}
|
||||
|
||||
// Is a given value a function?
|
||||
_.isFunction = function(obj) {
|
||||
return toString.call(obj) == '[object Function]';
|
||||
};
|
||||
|
||||
// Is a given value a string?
|
||||
_.isString = function(obj) {
|
||||
return toString.call(obj) == '[object String]';
|
||||
};
|
||||
|
||||
// Is a given value a number?
|
||||
_.isNumber = function(obj) {
|
||||
return toString.call(obj) == '[object Number]';
|
||||
};
|
||||
|
||||
// Is the given value `NaN`?
|
||||
_.isNaN = function(obj) {
|
||||
// `NaN` is the only value for which `===` is not reflexive.
|
||||
return obj !== obj;
|
||||
};
|
||||
|
||||
// Is a given value a boolean?
|
||||
_.isBoolean = function(obj) {
|
||||
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
||||
};
|
||||
|
||||
// Is a given value a date?
|
||||
_.isDate = function(obj) {
|
||||
return toString.call(obj) == '[object Date]';
|
||||
};
|
||||
|
||||
// Is the given value a regular expression?
|
||||
_.isRegExp = function(obj) {
|
||||
return toString.call(obj) == '[object RegExp]';
|
||||
};
|
||||
|
||||
// Is a given value equal to null?
|
||||
_.isNull = function(obj) {
|
||||
return obj === null;
|
||||
};
|
||||
|
||||
// Is a given variable undefined?
|
||||
_.isUndefined = function(obj) {
|
||||
return obj === void 0;
|
||||
};
|
||||
|
||||
// Has own property?
|
||||
_.has = function(obj, key) {
|
||||
return hasOwnProperty.call(obj, key);
|
||||
};
|
||||
|
||||
// Utility Functions
|
||||
// -----------------
|
||||
|
||||
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||||
// previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = function() {
|
||||
root._ = previousUnderscore;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Keep the identity function around for default iterators.
|
||||
_.identity = function(value) {
|
||||
return value;
|
||||
};
|
||||
|
||||
// Run a function **n** times.
|
||||
_.times = function (n, iterator, context) {
|
||||
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||
};
|
||||
|
||||
// Escape a string for HTML interpolation.
|
||||
_.escape = function(string) {
|
||||
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
||||
};
|
||||
|
||||
// Add your own custom functions to the Underscore object, ensuring that
|
||||
// they're correctly added to the OOP wrapper as well.
|
||||
_.mixin = function(obj) {
|
||||
each(_.functions(obj), function(name){
|
||||
addToWrapper(name, _[name] = obj[name]);
|
||||
});
|
||||
};
|
||||
|
||||
// Generate a unique integer id (unique within the entire client session).
|
||||
// Useful for temporary DOM ids.
|
||||
var idCounter = 0;
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = idCounter++;
|
||||
return prefix ? prefix + id : id;
|
||||
};
|
||||
|
||||
// By default, Underscore uses ERB-style template delimiters, change the
|
||||
// following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
evaluate : /<%([\s\S]+?)%>/g,
|
||||
interpolate : /<%=([\s\S]+?)%>/g,
|
||||
escape : /<%-([\s\S]+?)%>/g
|
||||
};
|
||||
|
||||
// When customizing `templateSettings`, if you don't want to define an
|
||||
// interpolation, evaluation or escaping regex, we need one that is
|
||||
// guaranteed not to match.
|
||||
var noMatch = /.^/;
|
||||
|
||||
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
||||
// that had been previously added.
|
||||
var unescape = function(code) {
|
||||
return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
|
||||
};
|
||||
|
||||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||
// and correctly escapes quotes within interpolated code.
|
||||
_.template = function(str, data) {
|
||||
var c = _.templateSettings;
|
||||
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
||||
'with(obj||{}){__p.push(\'' +
|
||||
str.replace(/\\/g, '\\\\')
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(c.escape || noMatch, function(match, code) {
|
||||
return "',_.escape(" + unescape(code) + "),'";
|
||||
})
|
||||
.replace(c.interpolate || noMatch, function(match, code) {
|
||||
return "'," + unescape(code) + ",'";
|
||||
})
|
||||
.replace(c.evaluate || noMatch, function(match, code) {
|
||||
return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
||||
})
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
+ "');}return __p.join('');";
|
||||
var func = new Function('obj', '_', tmpl);
|
||||
if (data) return func(data, _);
|
||||
return function(data) {
|
||||
return func.call(this, data, _);
|
||||
};
|
||||
};
|
||||
|
||||
// Add a "chain" function, which will delegate to the wrapper.
|
||||
_.chain = function(obj) {
|
||||
return _(obj).chain();
|
||||
};
|
||||
|
||||
// The OOP Wrapper
|
||||
// ---------------
|
||||
|
||||
// If Underscore is called as a function, it returns a wrapped object that
|
||||
// can be used OO-style. This wrapper holds altered versions of all the
|
||||
// underscore functions. Wrapped objects may be chained.
|
||||
var wrapper = function(obj) { this._wrapped = obj; };
|
||||
|
||||
// Expose `wrapper.prototype` as `_.prototype`
|
||||
_.prototype = wrapper.prototype;
|
||||
|
||||
// Helper function to continue chaining intermediate results.
|
||||
var result = function(obj, chain) {
|
||||
return chain ? _(obj).chain() : obj;
|
||||
};
|
||||
|
||||
// A method to easily add functions to the OOP wrapper.
|
||||
var addToWrapper = function(name, func) {
|
||||
wrapper.prototype[name] = function() {
|
||||
var args = slice.call(arguments);
|
||||
unshift.call(args, this._wrapped);
|
||||
return result(func.apply(_, args), this._chain);
|
||||
};
|
||||
};
|
||||
|
||||
// Add all of the Underscore functions to the wrapper object.
|
||||
_.mixin(_);
|
||||
|
||||
// Add all mutator Array functions to the wrapper.
|
||||
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||
var method = ArrayProto[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
var wrapped = this._wrapped;
|
||||
method.apply(wrapped, arguments);
|
||||
var length = wrapped.length;
|
||||
if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
|
||||
return result(wrapped, this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Add all accessor Array functions to the wrapper.
|
||||
each(['concat', 'join', 'slice'], function(name) {
|
||||
var method = ArrayProto[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Start chaining a wrapped Underscore object.
|
||||
wrapper.prototype.chain = function() {
|
||||
this._chain = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Extracts the result from a wrapped and chained object.
|
||||
wrapper.prototype.value = function() {
|
||||
return this._wrapped;
|
||||
};
|
||||
|
||||
}).call(this);
|
Reference in New Issue
Block a user